]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs5.patch
- up to 5.3.0
[packages/kernel.git] / kernel-aufs5.patch
CommitLineData
2121bcd9 1SPDX-License-Identifier: GPL-2.0
fbc438ed 2aufs5.x-rcN kbuild patch
7f207e10 3
fbc438ed 4diff --git a/fs/Kconfig b/fs/Kconfig
eca34b5c 5index bfb1c6095c7a..bddba5bb307e 100644
fbc438ed
JR
6--- a/fs/Kconfig
7+++ b/fs/Kconfig
eca34b5c 8@@ -261,6 +261,7 @@ source "fs/romfs/Kconfig"
83b672a5 9 source "fs/pstore/Kconfig"
5527c038 10 source "fs/sysv/Kconfig"
7e9cd9fe 11 source "fs/ufs/Kconfig"
7f207e10
AM
12+source "fs/aufs/Kconfig"
13
14 endif # MISC_FILESYSTEMS
15
16diff --git a/fs/Makefile b/fs/Makefile
eca34b5c 17index d60089fd689b..924c16a40b00 100644
7f207e10
AM
18--- a/fs/Makefile
19+++ b/fs/Makefile
fbc438ed 20@@ -130,3 +130,4 @@ obj-$(CONFIG_F2FS_FS) += f2fs/
7f207e10 21 obj-$(CONFIG_CEPH_FS) += ceph/
bf0370f2 22 obj-$(CONFIG_PSTORE) += pstore/
c06a8ce3 23 obj-$(CONFIG_EFIVAR_FS) += efivarfs/
86dc4139 24+obj-$(CONFIG_AUFS_FS) += aufs/
2121bcd9 25SPDX-License-Identifier: GPL-2.0
fbc438ed 26aufs5.x-rcN base patch
7f207e10 27
c1595e42 28diff --git a/MAINTAINERS b/MAINTAINERS
eca34b5c 29index 9cbcf167bdd0..5a9cee826a8f 100644
c1595e42
JR
30--- a/MAINTAINERS
31+++ b/MAINTAINERS
eca34b5c 32@@ -2822,6 +2822,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
eca34b5c 53index ab7ca5989097..80d06084b043 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
fbc438ed 95index 3d40771e8e7c..d62303c5472a 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)
103+int setfl(int fd, struct file * filp, unsigned long arg)
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
eca34b5c 117index 0f1e3b563c47..43df8452f97d 100644
5afbbe0d
AM
118--- a/fs/inode.c
119+++ b/fs/inode.c
fbc438ed 120@@ -1670,7 +1670,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
eca34b5c 130index d28d30b13043..34c8093ddb1d 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
eca34b5c 147index 5bbf587f5bc1..3265bb84f152 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;
162+ return ERR_PTR(-ENOSYS);
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;
173+ return ERR_PTR(-ENOSYS);
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
eca34b5c 221index 997a530ff4e9..3dbec51c2037 100644
5527c038
JR
222--- a/include/linux/fs.h
223+++ b/include/linux/fs.h
eca34b5c 224@@ -1331,6 +1331,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
228+extern int setfl(int fd, struct file * filp, unsigned long arg);
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);
eca34b5c 232@@ -1810,6 +1811,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);
eca34b5c 240@@ -1880,6 +1882,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 *);
eca34b5c 253@@ -2298,6 +2306,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;
eca34b5c 261@@ -2586,6 +2595,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
eca34b5c 270index 0b0d7259276d..12d18e180348 100644
8b6a4947
AM
271--- a/include/linux/lockdep.h
272+++ b/include/linux/lockdep.h
eca34b5c 273@@ -334,6 +334,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 *
eca34b5c 282@@ -476,6 +478,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
eca34b5c 325index 4861cf8e274b..ec87ccf82025 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
fbc438ed 346aufs5.x-rcN 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
eca34b5c 378index 731642e0f5a0..e8d6259de65b 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;
eca34b5c 393@@ -1807,7 +1810,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;
7e9cd9fe
AM
400 struct mm_walk walk = {
401 .hugetlb_entry = gather_hugetlb_stats,
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
eca34b5c 419index 0334ca97c584..3bdae823daee 100644
fb47a38f
JR
420--- a/include/linux/mm.h
421+++ b/include/linux/mm.h
eca34b5c 422@@ -1538,6 +1538,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
eca34b5c 452index 6a7a1083b6fb..461db8843e32 100644
fb47a38f
JR
453--- a/include/linux/mm_types.h
454+++ b/include/linux/mm_types.h
eca34b5c 455@@ -262,6 +262,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
eca34b5c 463@@ -336,6 +337,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
eca34b5c 472index 2852d0e76ea3..7b7f676b6465 100644
fb47a38f
JR
473--- a/kernel/fork.c
474+++ b/kernel/fork.c
eca34b5c 475@@ -553,7 +553,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
eca34b5c 485index d0b295c3b764..6156cd3d1ab0 100644
076b876e
AM
486--- a/mm/Makefile
487+++ b/mm/Makefile
acd2b654 488@@ -39,7 +39,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
eca34b5c 498index d0cf700bf201..5cac93e7bf67 100644
fb47a38f
JR
499--- a/mm/filemap.c
500+++ b/mm/filemap.c
eca34b5c 501@@ -2721,7 +2721,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
fbc438ed 511index 7e8c3e8ae75f..d8a903f61262 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;
fbc438ed 523@@ -931,7 +931,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);
fbc438ed 532@@ -1847,8 +1847,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);
fbc438ed 542@@ -2680,7 +2680,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);
fbc438ed 551@@ -2699,7 +2699,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));
fbc438ed 560@@ -2890,7 +2890,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);
fbc438ed 569@@ -2965,10 +2965,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)
fbc438ed 598@@ -3258,7 +3275,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
eca34b5c 608index fed1b6e9c89b..0d43b248ed54 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
ba1aed25 653index 000000000000..024cdcfae1b1
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+ *
ba1aed25 665+ * Copyright (c) 2014-2019 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
fbc438ed 744aufs5.x-rcN 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
eca34b5c 767index f7f6a140856a..1a740f3c42ba 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
fbc438ed 779index d62303c5472a..d4ad34463848 100644
febd17d6
JR
780--- a/fs/fcntl.c
781+++ b/fs/fcntl.c
2121bcd9 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
fbc438ed 791index b07b53f24ff5..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.
fbc438ed 802@@ -327,6 +328,7 @@ void flush_delayed_fput(void)
8cdd5066
JR
803 {
804 delayed_fput(NULL);
805 }
febd17d6 806+EXPORT_SYMBOL_GPL(flush_delayed_fput);
8cdd5066
JR
807
808 static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
809
fbc438ed 810@@ -374,6 +376,7 @@ void __fput_sync(struct file *file)
8cdd5066
JR
811 }
812
813 EXPORT_SYMBOL(fput);
febd17d6 814+EXPORT_SYMBOL_GPL(__fput_sync);
8cdd5066 815
79b8bda9 816 void __init files_init(void)
8b6a4947 817 {
5afbbe0d 818diff --git a/fs/inode.c b/fs/inode.c
eca34b5c 819index 43df8452f97d..8a5c14630ff0 100644
5afbbe0d
AM
820--- a/fs/inode.c
821+++ b/fs/inode.c
fbc438ed 822@@ -1679,6 +1679,7 @@ int update_time(struct inode *inode, struct timespec64 *time, int flags)
5afbbe0d
AM
823
824 return update_time(inode, time, flags);
825 }
826+EXPORT_SYMBOL_GPL(update_time);
827
828 /**
829 * touch_atime - update the access time
7f207e10 830diff --git a/fs/namespace.c b/fs/namespace.c
eca34b5c 831index 34c8093ddb1d..2b64af58b643 100644
7f207e10
AM
832--- a/fs/namespace.c
833+++ b/fs/namespace.c
eca34b5c 834@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
c06a8ce3
AM
835 mnt_dec_writers(real_mount(mnt));
836 preempt_enable();
837 }
838+EXPORT_SYMBOL_GPL(__mnt_drop_write);
839
840 /**
841 * mnt_drop_write - give up write access to a mount
eca34b5c 842@@ -781,6 +782,7 @@ int is_current_mnt_ns(struct vfsmount *mnt)
8b6a4947
AM
843 {
844 return check_mnt(real_mount(mnt));
845 }
846+EXPORT_SYMBOL_GPL(is_current_mnt_ns);
847
848 /*
849 * vfsmount lock must be held for write
eca34b5c 850@@ -1900,6 +1902,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
851 }
852 return 0;
853 }
febd17d6 854+EXPORT_SYMBOL_GPL(iterate_mounts);
7f207e10 855
fbc438ed 856 static void lock_mnt_tree(struct mount *mnt)
7f207e10
AM
857 {
858diff --git a/fs/notify/group.c b/fs/notify/group.c
fbc438ed 859index 0391190305cc..0b9f7f6d8390 100644
7f207e10
AM
860--- a/fs/notify/group.c
861+++ b/fs/notify/group.c
fbc438ed 862@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
1716fcea 863 {
2121bcd9 864 refcount_inc(&group->refcnt);
1716fcea 865 }
febd17d6 866+EXPORT_SYMBOL_GPL(fsnotify_get_group);
1716fcea
AM
867
868 /*
869 * Drop a reference to a group. Free it if it's through.
fbc438ed 870@@ -108,6 +109,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
2121bcd9 871 if (refcount_dec_and_test(&group->refcnt))
1716fcea 872 fsnotify_final_destroy_group(group);
7f207e10 873 }
febd17d6 874+EXPORT_SYMBOL_GPL(fsnotify_put_group);
7f207e10
AM
875
876 /*
877 * Create a new fsnotify_group and hold a reference for the group returned.
fbc438ed 878@@ -137,6 +139,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
7f207e10
AM
879
880 return group;
881 }
febd17d6 882+EXPORT_SYMBOL_GPL(fsnotify_alloc_group);
1716fcea
AM
883
884 int fsnotify_fasync(int fd, struct file *file, int on)
885 {
7f207e10 886diff --git a/fs/notify/mark.c b/fs/notify/mark.c
eca34b5c 887index 99ddd126f6f0..2154d69a2c7a 100644
7f207e10
AM
888--- a/fs/notify/mark.c
889+++ b/fs/notify/mark.c
fbc438ed 890@@ -276,6 +276,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
cd7a4cd9
AM
891 queue_delayed_work(system_unbound_wq, &reaper_work,
892 FSNOTIFY_REAPER_DELAY);
7f207e10 893 }
febd17d6 894+EXPORT_SYMBOL_GPL(fsnotify_put_mark);
7f207e10 895
cd7a4cd9
AM
896 /*
897 * Get mark reference when we found the mark via lockless traversal of object
fbc438ed 898@@ -430,6 +431,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark,
1716fcea 899 mutex_unlock(&group->mark_mutex);
79b8bda9 900 fsnotify_free_mark(mark);
7f207e10 901 }
febd17d6 902+EXPORT_SYMBOL_GPL(fsnotify_destroy_mark);
7f207e10 903
ffa93bbd
AM
904 /*
905 * Sorting function for lists of fsnotify marks.
eca34b5c 906@@ -685,6 +687,7 @@ int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
cd7a4cd9 907 mutex_unlock(&group->mark_mutex);
7f207e10
AM
908 return ret;
909 }
febd17d6 910+EXPORT_SYMBOL_GPL(fsnotify_add_mark);
7f207e10 911
cd7a4cd9
AM
912 /*
913 * Given a list of marks, find the mark associated with given group. If found
eca34b5c 914@@ -809,6 +812,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
ffa93bbd 915 mark->group = group;
fbc438ed 916 WRITE_ONCE(mark->connector, NULL);
7f207e10 917 }
febd17d6 918+EXPORT_SYMBOL_GPL(fsnotify_init_mark);
7f207e10 919
5afbbe0d
AM
920 /*
921 * Destroy all marks in destroy_list, waits for SRCU period to finish before
7f207e10 922diff --git a/fs/open.c b/fs/open.c
eca34b5c 923index a59abe3c669a..78809163ba03 100644
7f207e10
AM
924--- a/fs/open.c
925+++ b/fs/open.c
fbc438ed 926@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
febd17d6 927 inode_unlock(dentry->d_inode);
7f207e10
AM
928 return ret;
929 }
febd17d6 930+EXPORT_SYMBOL_GPL(do_truncate);
7f207e10 931
5afbbe0d 932 long vfs_truncate(const struct path *path, loff_t length)
7f207e10 933 {
5527c038 934diff --git a/fs/read_write.c b/fs/read_write.c
eca34b5c 935index 3265bb84f152..5b2dbddb0efe 100644
5527c038
JR
936--- a/fs/read_write.c
937+++ b/fs/read_write.c
fbc438ed 938@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
8b6a4947
AM
939
940 return ret;
941 }
942+EXPORT_SYMBOL_GPL(vfs_read);
943
944 static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
945 {
fbc438ed 946@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file)
5527c038
JR
947 return new_sync_read;
948 return ERR_PTR(-ENOSYS);
949 }
febd17d6 950+EXPORT_SYMBOL_GPL(vfs_readf);
5527c038
JR
951
952 vfs_writef_t vfs_writef(struct file *file)
953 {
fbc438ed 954@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *file)
5527c038
JR
955 return new_sync_write;
956 return ERR_PTR(-ENOSYS);
957 }
febd17d6 958+EXPORT_SYMBOL_GPL(vfs_writef);
5527c038 959
8b6a4947
AM
960 ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
961 {
fbc438ed 962@@ -588,6 +591,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
8b6a4947
AM
963
964 return ret;
965 }
966+EXPORT_SYMBOL_GPL(vfs_write);
967
fbc438ed
JR
968 /* file_ppos returns &file->f_pos or NULL if file is stream */
969 static inline loff_t *file_ppos(struct file *file)
7f207e10 970diff --git a/fs/splice.c b/fs/splice.c
eca34b5c 971index 75b489fcb66f..0a1f7498c22b 100644
7f207e10
AM
972--- a/fs/splice.c
973+++ b/fs/splice.c
fbc438ed 974@@ -847,6 +847,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
392086de
AM
975
976 return splice_write(pipe, out, ppos, len, flags);
7f207e10 977 }
febd17d6 978+EXPORT_SYMBOL_GPL(do_splice_from);
7f207e10
AM
979
980 /*
981 * Attempt to initiate a splice from a file to a pipe.
fbc438ed 982@@ -876,6 +877,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
7f207e10
AM
983
984 return splice_read(in, ppos, pipe, len, flags);
985 }
febd17d6 986+EXPORT_SYMBOL_GPL(do_splice_to);
7f207e10
AM
987
988 /**
989 * splice_direct_to_actor - splices data directly between two non-pipes
a2654f78 990diff --git a/fs/sync.c b/fs/sync.c
fbc438ed 991index 457f4e4a5cc1..67c66358f3fe 100644
a2654f78
AM
992--- a/fs/sync.c
993+++ b/fs/sync.c
2121bcd9 994@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block *sb, int wait)
a2654f78
AM
995 sb->s_op->sync_fs(sb, wait);
996 return __sync_blockdev(sb->s_bdev, wait);
997 }
998+EXPORT_SYMBOL_GPL(__sync_filesystem);
999
1000 /*
1001 * Write out and wait upon all dirty data associated with this
c1595e42 1002diff --git a/fs/xattr.c b/fs/xattr.c
fbc438ed 1003index 90dd78f0eb27..40b01dd1b14a 100644
c1595e42
JR
1004--- a/fs/xattr.c
1005+++ b/fs/xattr.c
fbc438ed 1006@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
c1595e42
JR
1007 *xattr_value = value;
1008 return error;
1009 }
febd17d6 1010+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
c1595e42 1011
febd17d6 1012 ssize_t
f2c43d5f 1013 __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
8b6a4947 1014diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
eca34b5c 1015index ec87ccf82025..739d1c8a81f5 100644
8b6a4947
AM
1016--- a/kernel/locking/lockdep.c
1017+++ b/kernel/locking/lockdep.c
eca34b5c
AM
1018@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
1019 */
1020 return lock_classes + class_idx;
8b6a4947
AM
1021 }
1022+EXPORT_SYMBOL_GPL(lockdep_hlock_class);
1023 #define hlock_class(hlock) lockdep_hlock_class(hlock)
1024
1025 #ifdef CONFIG_LOCK_STAT
8cdd5066 1026diff --git a/kernel/task_work.c b/kernel/task_work.c
ba1aed25 1027index 0fef395662a6..83fb1ecfc33d 100644
8cdd5066
JR
1028--- a/kernel/task_work.c
1029+++ b/kernel/task_work.c
2121bcd9 1030@@ -116,3 +116,4 @@ void task_work_run(void)
8cdd5066
JR
1031 } while (work);
1032 }
1033 }
febd17d6 1034+EXPORT_SYMBOL_GPL(task_work_run);
7f207e10 1035diff --git a/security/device_cgroup.c b/security/device_cgroup.c
eca34b5c 1036index 725674f3276d..83f6494c52a2 100644
7f207e10
AM
1037--- a/security/device_cgroup.c
1038+++ b/security/device_cgroup.c
83b672a5 1039@@ -824,3 +824,4 @@ int __devcgroup_check_permission(short type, u32 major, u32 minor,
7f207e10 1040
2121bcd9
AM
1041 return 0;
1042 }
1043+EXPORT_SYMBOL_GPL(__devcgroup_check_permission);
7f207e10 1044diff --git a/security/security.c b/security/security.c
eca34b5c 1045index 250ee2d76406..2765042d4846 100644
7f207e10
AM
1046--- a/security/security.c
1047+++ b/security/security.c
eca34b5c 1048@@ -996,6 +996,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
7f207e10 1049 return 0;
c2c0f25c 1050 return call_int_hook(path_rmdir, 0, dir, dentry);
7f207e10 1051 }
febd17d6 1052+EXPORT_SYMBOL_GPL(security_path_rmdir);
7f207e10 1053
5afbbe0d 1054 int security_path_unlink(const struct path *dir, struct dentry *dentry)
7f207e10 1055 {
eca34b5c 1056@@ -1012,6 +1013,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
7f207e10 1057 return 0;
c2c0f25c 1058 return call_int_hook(path_symlink, 0, dir, dentry, old_name);
7f207e10 1059 }
febd17d6 1060+EXPORT_SYMBOL_GPL(security_path_symlink);
7f207e10 1061
5afbbe0d 1062 int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
7f207e10 1063 struct dentry *new_dentry)
eca34b5c 1064@@ -1020,6 +1022,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
7f207e10 1065 return 0;
c2c0f25c 1066 return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
7f207e10 1067 }
febd17d6 1068+EXPORT_SYMBOL_GPL(security_path_link);
7f207e10 1069
5afbbe0d
AM
1070 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
1071 const struct path *new_dir, struct dentry *new_dentry,
eca34b5c 1072@@ -1047,6 +1050,7 @@ int security_path_truncate(const struct path *path)
7f207e10 1073 return 0;
c2c0f25c 1074 return call_int_hook(path_truncate, 0, path);
7f207e10 1075 }
febd17d6 1076+EXPORT_SYMBOL_GPL(security_path_truncate);
7f207e10 1077
5afbbe0d 1078 int security_path_chmod(const struct path *path, umode_t mode)
7eafdf33 1079 {
eca34b5c 1080@@ -1054,6 +1058,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
7f207e10 1081 return 0;
c2c0f25c 1082 return call_int_hook(path_chmod, 0, path, mode);
7f207e10 1083 }
febd17d6 1084+EXPORT_SYMBOL_GPL(security_path_chmod);
7f207e10 1085
5afbbe0d 1086 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
7f207e10 1087 {
eca34b5c 1088@@ -1061,6 +1066,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
7f207e10 1089 return 0;
c2c0f25c 1090 return call_int_hook(path_chown, 0, path, uid, gid);
7f207e10 1091 }
febd17d6 1092+EXPORT_SYMBOL_GPL(security_path_chown);
7f207e10 1093
5afbbe0d 1094 int security_path_chroot(const struct path *path)
7f207e10 1095 {
eca34b5c 1096@@ -1161,6 +1167,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 1097 return 0;
c2c0f25c 1098 return call_int_hook(inode_permission, 0, inode, mask);
7f207e10 1099 }
febd17d6 1100+EXPORT_SYMBOL_GPL(security_inode_permission);
7f207e10 1101
1e00d052 1102 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
7f207e10 1103 {
eca34b5c 1104@@ -1338,6 +1345,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
1105
1106 return fsnotify_perm(file, mask);
1107 }
febd17d6 1108+EXPORT_SYMBOL_GPL(security_file_permission);
7f207e10
AM
1109
1110 int security_file_alloc(struct file *file)
1111 {
7f207e10 1112diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
eca34b5c
AM
1113--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
1114+++ linux/Documentation/ABI/testing/debugfs-aufs 2019-07-11 15:42:14.455570938 +0200
062440b3 1115@@ -0,0 +1,55 @@
7f207e10
AM
1116+What: /debug/aufs/si_<id>/
1117+Date: March 2009
f6b6e03d 1118+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1119+Description:
1120+ Under /debug/aufs, a directory named si_<id> is created
1121+ per aufs mount, where <id> is a unique id generated
1122+ internally.
1facf9fc 1123+
86dc4139
AM
1124+What: /debug/aufs/si_<id>/plink
1125+Date: Apr 2013
f6b6e03d 1126+Contact: J. R. Okajima <hooanon05g@gmail.com>
86dc4139
AM
1127+Description:
1128+ It has three lines and shows the information about the
1129+ pseudo-link. The first line is a single number
1130+ representing a number of buckets. The second line is a
1131+ number of pseudo-links per buckets (separated by a
1132+ blank). The last line is a single number representing a
1133+ total number of psedo-links.
1134+ When the aufs mount option 'noplink' is specified, it
1135+ will show "1\n0\n0\n".
1136+
7f207e10
AM
1137+What: /debug/aufs/si_<id>/xib
1138+Date: March 2009
f6b6e03d 1139+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1140+Description:
1141+ It shows the consumed blocks by xib (External Inode Number
1142+ Bitmap), its block size and file size.
1143+ When the aufs mount option 'noxino' is specified, it
1144+ will be empty. About XINO files, see the aufs manual.
1145+
062440b3 1146+What: /debug/aufs/si_<id>/xi0, xi1 ... xiN and xiN-N
7f207e10 1147+Date: March 2009
f6b6e03d 1148+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1149+Description:
1150+ It shows the consumed blocks by xino (External Inode Number
1151+ Translation Table), its link count, block size and file
1152+ size.
062440b3
AM
1153+ Due to the file size limit, there may exist multiple
1154+ xino files per branch. In this case, "-N" is added to
1155+ the filename and it corresponds to the index of the
1156+ internal xino array. "-0" is omitted.
1157+ When the aufs mount option 'noxino' is specified, Those
1158+ entries won't exist. About XINO files, see the aufs
1159+ manual.
7f207e10
AM
1160+
1161+What: /debug/aufs/si_<id>/xigen
1162+Date: March 2009
f6b6e03d 1163+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1164+Description:
1165+ It shows the consumed blocks by xigen (External Inode
1166+ Generation Table), its block size and file size.
1167+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
1168+ be created.
1169+ When the aufs mount option 'noxino' is specified, it
1170+ will be empty. About XINO files, see the aufs manual.
1171diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
eca34b5c
AM
1172--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
1173+++ linux/Documentation/ABI/testing/sysfs-aufs 2019-07-11 15:42:14.455570938 +0200
392086de 1174@@ -0,0 +1,31 @@
7f207e10
AM
1175+What: /sys/fs/aufs/si_<id>/
1176+Date: March 2009
f6b6e03d 1177+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1178+Description:
1179+ Under /sys/fs/aufs, a directory named si_<id> is created
1180+ per aufs mount, where <id> is a unique id generated
1181+ internally.
1182+
1183+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
1184+Date: March 2009
f6b6e03d 1185+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1186+Description:
1187+ It shows the abolute path of a member directory (which
1188+ is called branch) in aufs, and its permission.
1189+
392086de
AM
1190+What: /sys/fs/aufs/si_<id>/brid0, brid1 ... bridN
1191+Date: July 2013
f6b6e03d 1192+Contact: J. R. Okajima <hooanon05g@gmail.com>
392086de
AM
1193+Description:
1194+ It shows the id of a member directory (which is called
1195+ branch) in aufs.
1196+
7f207e10
AM
1197+What: /sys/fs/aufs/si_<id>/xi_path
1198+Date: March 2009
f6b6e03d 1199+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1200+Description:
1201+ It shows the abolute path of XINO (External Inode Number
1202+ Bitmap, Translation Table and Generation Table) file
1203+ even if it is the default path.
1204+ When the aufs mount option 'noxino' is specified, it
1205+ will be empty. About XINO files, see the aufs manual.
53392da6 1206diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
eca34b5c
AM
1207--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
1208+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2019-07-11 15:42:14.455570938 +0200
1c60b727 1209@@ -0,0 +1,171 @@
53392da6 1210+
ba1aed25 1211+# Copyright (C) 2005-2019 Junjiro R. Okajima
53392da6
AM
1212+#
1213+# This program is free software; you can redistribute it and/or modify
1214+# it under the terms of the GNU General Public License as published by
1215+# the Free Software Foundation; either version 2 of the License, or
1216+# (at your option) any later version.
1217+#
1218+# This program is distributed in the hope that it will be useful,
1219+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1220+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1221+# GNU General Public License for more details.
1222+#
1223+# You should have received a copy of the GNU General Public License
523b37e3 1224+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1225+
1226+Introduction
1227+----------------------------------------
1228+
3c1bdaff 1229+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s]
53392da6
AM
1230+1. abbrev. for "advanced multi-layered unification filesystem".
1231+2. abbrev. for "another unionfs".
1232+3. abbrev. for "auf das" in German which means "on the" in English.
1233+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
1234+ But "Filesystem aufs Filesystem" is hard to understand.
1c60b727 1235+4. abbrev. for "African Urban Fashion Show".
53392da6
AM
1236+
1237+AUFS is a filesystem with features:
1238+- multi layered stackable unification filesystem, the member directory
1239+ is called as a branch.
1240+- branch permission and attribute, 'readonly', 'real-readonly',
7e9cd9fe 1241+ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their
53392da6
AM
1242+ combination.
1243+- internal "file copy-on-write".
1244+- logical deletion, whiteout.
1245+- dynamic branch manipulation, adding, deleting and changing permission.
1246+- allow bypassing aufs, user's direct branch access.
1247+- external inode number translation table and bitmap which maintains the
1248+ persistent aufs inode number.
1249+- seekable directory, including NFS readdir.
1250+- file mapping, mmap and sharing pages.
1251+- pseudo-link, hardlink over branches.
1252+- loopback mounted filesystem as a branch.
1253+- several policies to select one among multiple writable branches.
1254+- revert a single systemcall when an error occurs in aufs.
1255+- and more...
1256+
1257+
1258+Multi Layered Stackable Unification Filesystem
1259+----------------------------------------------------------------------
1260+Most people already knows what it is.
1261+It is a filesystem which unifies several directories and provides a
1262+merged single directory. When users access a file, the access will be
1263+passed/re-directed/converted (sorry, I am not sure which English word is
1264+correct) to the real file on the member filesystem. The member
1265+filesystem is called 'lower filesystem' or 'branch' and has a mode
1266+'readonly' and 'readwrite.' And the deletion for a file on the lower
1267+readonly branch is handled by creating 'whiteout' on the upper writable
1268+branch.
1269+
1270+On LKML, there have been discussions about UnionMount (Jan Blunck,
1271+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
1272+different approaches to implement the merged-view.
1273+The former tries putting it into VFS, and the latter implements as a
1274+separate filesystem.
1275+(If I misunderstand about these implementations, please let me know and
1276+I shall correct it. Because it is a long time ago when I read their
1277+source files last time).
1278+
1279+UnionMount's approach will be able to small, but may be hard to share
1280+branches between several UnionMount since the whiteout in it is
1281+implemented in the inode on branch filesystem and always
1282+shared. According to Bharata's post, readdir does not seems to be
1283+finished yet.
1284+There are several missing features known in this implementations such as
1285+- for users, the inode number may change silently. eg. copy-up.
1286+- link(2) may break by copy-up.
1287+- read(2) may get an obsoleted filedata (fstat(2) too).
1288+- fcntl(F_SETLK) may be broken by copy-up.
1289+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
1290+ open(O_RDWR).
1291+
7e9cd9fe
AM
1292+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was
1293+merged into mainline. This is another implementation of UnionMount as a
1294+separated filesystem. All the limitations and known problems which
1295+UnionMount are equally inherited to "overlay" filesystem.
1296+
1297+Unionfs has a longer history. When I started implementing a stackable
1298+filesystem (Aug 2005), it already existed. It has virtual super_block,
1299+inode, dentry and file objects and they have an array pointing lower
1300+same kind objects. After contributing many patches for Unionfs, I
1301+re-started my project AUFS (Jun 2006).
53392da6
AM
1302+
1303+In AUFS, the structure of filesystem resembles to Unionfs, but I
1304+implemented my own ideas, approaches and enhancements and it became
1305+totally different one.
1306+
1307+Comparing DM snapshot and fs based implementation
1308+- the number of bytes to be copied between devices is much smaller.
1309+- the type of filesystem must be one and only.
1310+- the fs must be writable, no readonly fs, even for the lower original
1311+ device. so the compression fs will not be usable. but if we use
1312+ loopback mount, we may address this issue.
1313+ for instance,
1314+ mount /cdrom/squashfs.img /sq
1315+ losetup /sq/ext2.img
1316+ losetup /somewhere/cow
1317+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
1318+- it will be difficult (or needs more operations) to extract the
1319+ difference between the original device and COW.
1320+- DM snapshot-merge may help a lot when users try merging. in the
1321+ fs-layer union, users will use rsync(1).
1322+
7e9cd9fe
AM
1323+You may want to read my old paper "Filesystems in LiveCD"
1324+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf).
53392da6 1325+
7e9cd9fe
AM
1326+
1327+Several characters/aspects/persona of aufs
53392da6
AM
1328+----------------------------------------------------------------------
1329+
7e9cd9fe 1330+Aufs has several characters, aspects or persona.
53392da6
AM
1331+1. a filesystem, callee of VFS helper
1332+2. sub-VFS, caller of VFS helper for branches
1333+3. a virtual filesystem which maintains persistent inode number
1334+4. reader/writer of files on branches such like an application
1335+
1336+1. Callee of VFS Helper
1337+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
1338+unlink(2) from an application reaches sys_unlink() kernel function and
1339+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
1340+calls filesystem specific unlink operation. Actually aufs implements the
1341+unlink operation but it behaves like a redirector.
1342+
1343+2. Caller of VFS Helper for Branches
1344+aufs_unlink() passes the unlink request to the branch filesystem as if
1345+it were called from VFS. So the called unlink operation of the branch
1346+filesystem acts as usual. As a caller of VFS helper, aufs should handle
1347+every necessary pre/post operation for the branch filesystem.
1348+- acquire the lock for the parent dir on a branch
1349+- lookup in a branch
1350+- revalidate dentry on a branch
1351+- mnt_want_write() for a branch
1352+- vfs_unlink() for a branch
1353+- mnt_drop_write() for a branch
1354+- release the lock on a branch
1355+
1356+3. Persistent Inode Number
1357+One of the most important issue for a filesystem is to maintain inode
1358+numbers. This is particularly important to support exporting a
1359+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
1360+backend block device for its own. But some storage is necessary to
7e9cd9fe
AM
1361+keep and maintain the inode numbers. It may be a large space and may not
1362+suit to keep in memory. Aufs rents some space from its first writable
1363+branch filesystem (by default) and creates file(s) on it. These files
1364+are created by aufs internally and removed soon (currently) keeping
1365+opened.
53392da6
AM
1366+Note: Because these files are removed, they are totally gone after
1367+ unmounting aufs. It means the inode numbers are not persistent
1368+ across unmount or reboot. I have a plan to make them really
1369+ persistent which will be important for aufs on NFS server.
1370+
1371+4. Read/Write Files Internally (copy-on-write)
1372+Because a branch can be readonly, when you write a file on it, aufs will
1373+"copy-up" it to the upper writable branch internally. And then write the
1374+originally requested thing to the file. Generally kernel doesn't
1375+open/read/write file actively. In aufs, even a single write may cause a
1376+internal "file copy". This behaviour is very similar to cp(1) command.
1377+
1378+Some people may think it is better to pass such work to user space
1379+helper, instead of doing in kernel space. Actually I am still thinking
1380+about it. But currently I have implemented it in kernel space.
1381diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
eca34b5c
AM
1382--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
1383+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2019-07-11 15:42:14.455570938 +0200
7e9cd9fe 1384@@ -0,0 +1,258 @@
53392da6 1385+
ba1aed25 1386+# Copyright (C) 2005-2019 Junjiro R. Okajima
53392da6
AM
1387+#
1388+# This program is free software; you can redistribute it and/or modify
1389+# it under the terms of the GNU General Public License as published by
1390+# the Free Software Foundation; either version 2 of the License, or
1391+# (at your option) any later version.
1392+#
1393+# This program is distributed in the hope that it will be useful,
1394+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1395+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1396+# GNU General Public License for more details.
1397+#
1398+# You should have received a copy of the GNU General Public License
523b37e3 1399+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1400+
1401+Basic Aufs Internal Structure
1402+
1403+Superblock/Inode/Dentry/File Objects
1404+----------------------------------------------------------------------
1405+As like an ordinary filesystem, aufs has its own
1406+superblock/inode/dentry/file objects. All these objects have a
1407+dynamically allocated array and store the same kind of pointers to the
1408+lower filesystem, branch.
1409+For example, when you build a union with one readwrite branch and one
1410+readonly, mounted /au, /rw and /ro respectively.
1411+- /au = /rw + /ro
1412+- /ro/fileA exists but /rw/fileA
1413+
1414+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
1415+pointers are stored in a aufs dentry. The array in aufs dentry will be,
7e9cd9fe 1416+- [0] = NULL (because /rw/fileA doesn't exist)
53392da6
AM
1417+- [1] = /ro/fileA
1418+
1419+This style of an array is essentially same to the aufs
1420+superblock/inode/dentry/file objects.
1421+
1422+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
1423+branches dynamically, these objects has its own generation. When
1424+branches are changed, the generation in aufs superblock is
1425+incremented. And a generation in other object are compared when it is
1426+accessed. When a generation in other objects are obsoleted, aufs
1427+refreshes the internal array.
53392da6
AM
1428+
1429+
1430+Superblock
1431+----------------------------------------------------------------------
1432+Additionally aufs superblock has some data for policies to select one
1433+among multiple writable branches, XIB files, pseudo-links and kobject.
1434+See below in detail.
7e9cd9fe
AM
1435+About the policies which supports copy-down a directory, see
1436+wbr_policy.txt too.
53392da6
AM
1437+
1438+
1439+Branch and XINO(External Inode Number Translation Table)
1440+----------------------------------------------------------------------
1441+Every branch has its own xino (external inode number translation table)
1442+file. The xino file is created and unlinked by aufs internally. When two
1443+members of a union exist on the same filesystem, they share the single
1444+xino file.
1445+The struct of a xino file is simple, just a sequence of aufs inode
1446+numbers which is indexed by the lower inode number.
1447+In the above sample, assume the inode number of /ro/fileA is i111 and
1448+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
1449+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
1450+
1451+When the inode numbers are not contiguous, the xino file will be sparse
1452+which has a hole in it and doesn't consume as much disk space as it
1453+might appear. If your branch filesystem consumes disk space for such
1454+holes, then you should specify 'xino=' option at mounting aufs.
1455+
7e9cd9fe
AM
1456+Aufs has a mount option to free the disk blocks for such holes in XINO
1457+files on tmpfs or ramdisk. But it is not so effective actually. If you
1458+meet a problem of disk shortage due to XINO files, then you should try
1459+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git.
1460+The patch localizes the assignment inumbers per tmpfs-mount and avoid
1461+the holes in XINO files.
1462+
53392da6 1463+Also a writable branch has three kinds of "whiteout bases". All these
7e9cd9fe 1464+are existed when the branch is joined to aufs, and their names are
53392da6
AM
1465+whiteout-ed doubly, so that users will never see their names in aufs
1466+hierarchy.
7e9cd9fe 1467+1. a regular file which will be hardlinked to all whiteouts.
53392da6 1468+2. a directory to store a pseudo-link.
7e9cd9fe 1469+3. a directory to store an "orphan"-ed file temporary.
53392da6
AM
1470+
1471+1. Whiteout Base
1472+ When you remove a file on a readonly branch, aufs handles it as a
1473+ logical deletion and creates a whiteout on the upper writable branch
1474+ as a hardlink of this file in order not to consume inode on the
1475+ writable branch.
1476+2. Pseudo-link Dir
1477+ See below, Pseudo-link.
1478+3. Step-Parent Dir
1479+ When "fileC" exists on the lower readonly branch only and it is
1480+ opened and removed with its parent dir, and then user writes
1481+ something into it, then aufs copies-up fileC to this
1482+ directory. Because there is no other dir to store fileC. After
1483+ creating a file under this dir, the file is unlinked.
1484+
1485+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
1486+dynamically, a branch has its own id. When the branch order changes,
1487+aufs finds the new index by searching the branch id.
53392da6
AM
1488+
1489+
1490+Pseudo-link
1491+----------------------------------------------------------------------
1492+Assume "fileA" exists on the lower readonly branch only and it is
1493+hardlinked to "fileB" on the branch. When you write something to fileA,
1494+aufs copies-up it to the upper writable branch. Additionally aufs
1495+creates a hardlink under the Pseudo-link Directory of the writable
1496+branch. The inode of a pseudo-link is kept in aufs super_block as a
1497+simple list. If fileB is read after unlinking fileA, aufs returns
1498+filedata from the pseudo-link instead of the lower readonly
1499+branch. Because the pseudo-link is based upon the inode, to keep the
7e9cd9fe 1500+inode number by xino (see above) is essentially necessary.
53392da6
AM
1501+
1502+All the hardlinks under the Pseudo-link Directory of the writable branch
1503+should be restored in a proper location later. Aufs provides a utility
1504+to do this. The userspace helpers executed at remounting and unmounting
1505+aufs by default.
1506+During this utility is running, it puts aufs into the pseudo-link
1507+maintenance mode. In this mode, only the process which began the
1508+maintenance mode (and its child processes) is allowed to operate in
1509+aufs. Some other processes which are not related to the pseudo-link will
1510+be allowed to run too, but the rest have to return an error or wait
1511+until the maintenance mode ends. If a process already acquires an inode
1512+mutex (in VFS), it has to return an error.
1513+
1514+
1515+XIB(external inode number bitmap)
1516+----------------------------------------------------------------------
1517+Addition to the xino file per a branch, aufs has an external inode number
7e9cd9fe
AM
1518+bitmap in a superblock object. It is also an internal file such like a
1519+xino file.
53392da6
AM
1520+It is a simple bitmap to mark whether the aufs inode number is in-use or
1521+not.
1522+To reduce the file I/O, aufs prepares a single memory page to cache xib.
1523+
7e9cd9fe 1524+As well as XINO files, aufs has a feature to truncate/refresh XIB to
53392da6
AM
1525+reduce the number of consumed disk blocks for these files.
1526+
1527+
1528+Virtual or Vertical Dir, and Readdir in Userspace
1529+----------------------------------------------------------------------
1530+In order to support multiple layers (branches), aufs readdir operation
1531+constructs a virtual dir block on memory. For readdir, aufs calls
1532+vfs_readdir() internally for each dir on branches, merges their entries
1533+with eliminating the whiteout-ed ones, and sets it to file (dir)
1534+object. So the file object has its entry list until it is closed. The
1535+entry list will be updated when the file position is zero and becomes
7e9cd9fe 1536+obsoleted. This decision is made in aufs automatically.
53392da6
AM
1537+
1538+The dynamically allocated memory block for the name of entries has a
1539+unit of 512 bytes (by default) and stores the names contiguously (no
1540+padding). Another block for each entry is handled by kmem_cache too.
1541+During building dir blocks, aufs creates hash list and judging whether
1542+the entry is whiteouted by its upper branch or already listed.
1543+The merged result is cached in the corresponding inode object and
1544+maintained by a customizable life-time option.
1545+
1546+Some people may call it can be a security hole or invite DoS attack
1547+since the opened and once readdir-ed dir (file object) holds its entry
1548+list and becomes a pressure for system memory. But I'd say it is similar
1549+to files under /proc or /sys. The virtual files in them also holds a
1550+memory page (generally) while they are opened. When an idea to reduce
1551+memory for them is introduced, it will be applied to aufs too.
1552+For those who really hate this situation, I've developed readdir(3)
1553+library which operates this merging in userspace. You just need to set
1554+LD_PRELOAD environment variable, and aufs will not consume no memory in
1555+kernel space for readdir(3).
1556+
1557+
1558+Workqueue
1559+----------------------------------------------------------------------
1560+Aufs sometimes requires privilege access to a branch. For instance,
1561+in copy-up/down operation. When a user process is going to make changes
1562+to a file which exists in the lower readonly branch only, and the mode
1563+of one of ancestor directories may not be writable by a user
1564+process. Here aufs copy-up the file with its ancestors and they may
1565+require privilege to set its owner/group/mode/etc.
1566+This is a typical case of a application character of aufs (see
1567+Introduction).
1568+
1569+Aufs uses workqueue synchronously for this case. It creates its own
1570+workqueue. The workqueue is a kernel thread and has privilege. Aufs
1571+passes the request to call mkdir or write (for example), and wait for
1572+its completion. This approach solves a problem of a signal handler
1573+simply.
1574+If aufs didn't adopt the workqueue and changed the privilege of the
7e9cd9fe
AM
1575+process, then the process may receive the unexpected SIGXFSZ or other
1576+signals.
53392da6
AM
1577+
1578+Also aufs uses the system global workqueue ("events" kernel thread) too
1579+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
1580+whiteout base and etc. This is unrelated to a privilege.
1581+Most of aufs operation tries acquiring a rw_semaphore for aufs
1582+superblock at the beginning, at the same time waits for the completion
1583+of all queued asynchronous tasks.
1584+
1585+
1586+Whiteout
1587+----------------------------------------------------------------------
1588+The whiteout in aufs is very similar to Unionfs's. That is represented
1589+by its filename. UnionMount takes an approach of a file mode, but I am
1590+afraid several utilities (find(1) or something) will have to support it.
1591+
1592+Basically the whiteout represents "logical deletion" which stops aufs to
1593+lookup further, but also it represents "dir is opaque" which also stop
7e9cd9fe 1594+further lookup.
53392da6
AM
1595+
1596+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
1597+In order to make several functions in a single systemcall to be
1598+revertible, aufs adopts an approach to rename a directory to a temporary
1599+unique whiteouted name.
1600+For example, in rename(2) dir where the target dir already existed, aufs
1601+renames the target dir to a temporary unique whiteouted name before the
7e9cd9fe 1602+actual rename on a branch, and then handles other actions (make it opaque,
53392da6
AM
1603+update the attributes, etc). If an error happens in these actions, aufs
1604+simply renames the whiteouted name back and returns an error. If all are
1605+succeeded, aufs registers a function to remove the whiteouted unique
1606+temporary name completely and asynchronously to the system global
1607+workqueue.
1608+
1609+
1610+Copy-up
1611+----------------------------------------------------------------------
1612+It is a well-known feature or concept.
1613+When user modifies a file on a readonly branch, aufs operate "copy-up"
1614+internally and makes change to the new file on the upper writable branch.
1615+When the trigger systemcall does not update the timestamps of the parent
1616+dir, aufs reverts it after copy-up.
c2b27bf2
AM
1617+
1618+
1619+Move-down (aufs3.9 and later)
1620+----------------------------------------------------------------------
1621+"Copy-up" is one of the essential feature in aufs. It copies a file from
1622+the lower readonly branch to the upper writable branch when a user
1623+changes something about the file.
1624+"Move-down" is an opposite action of copy-up. Basically this action is
1625+ran manually instead of automatically and internally.
076b876e
AM
1626+For desgin and implementation, aufs has to consider these issues.
1627+- whiteout for the file may exist on the lower branch.
1628+- ancestor directories may not exist on the lower branch.
1629+- diropq for the ancestor directories may exist on the upper branch.
1630+- free space on the lower branch will reduce.
1631+- another access to the file may happen during moving-down, including
7e9cd9fe 1632+ UDBA (see "Revalidate Dentry and UDBA").
076b876e
AM
1633+- the file should not be hard-linked nor pseudo-linked. they should be
1634+ handled by auplink utility later.
c2b27bf2
AM
1635+
1636+Sometimes users want to move-down a file from the upper writable branch
1637+to the lower readonly or writable branch. For instance,
1638+- the free space of the upper writable branch is going to run out.
1639+- create a new intermediate branch between the upper and lower branch.
1640+- etc.
1641+
1642+For this purpose, use "aumvdown" command in aufs-util.git.
b912730e 1643diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt linux/Documentation/filesystems/aufs/design/03atomic_open.txt
eca34b5c
AM
1644--- /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 01:00:00.000000000 +0100
1645+++ linux/Documentation/filesystems/aufs/design/03atomic_open.txt 2019-07-11 15:42:14.458904362 +0200
b912730e
AM
1646@@ -0,0 +1,85 @@
1647+
ba1aed25 1648+# Copyright (C) 2015-2019 Junjiro R. Okajima
b912730e
AM
1649+#
1650+# This program is free software; you can redistribute it and/or modify
1651+# it under the terms of the GNU General Public License as published by
1652+# the Free Software Foundation; either version 2 of the License, or
1653+# (at your option) any later version.
1654+#
1655+# This program is distributed in the hope that it will be useful,
1656+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1657+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1658+# GNU General Public License for more details.
1659+#
1660+# You should have received a copy of the GNU General Public License
1661+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1662+
1663+Support for a branch who has its ->atomic_open()
1664+----------------------------------------------------------------------
1665+The filesystems who implement its ->atomic_open() are not majority. For
1666+example NFSv4 does, and aufs should call NFSv4 ->atomic_open,
1667+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than
1668+->atomic_open(), NFSv4 returns an error for this open(2). While I am not
1669+sure whether all filesystems who have ->atomic_open() behave like this,
1670+but NFSv4 surely returns the error.
1671+
1672+In order to support ->atomic_open() for aufs, there are a few
1673+approaches.
1674+
1675+A. Introduce aufs_atomic_open()
1676+ - calls one of VFS:do_last(), lookup_open() or atomic_open() for
1677+ branch fs.
1678+B. Introduce aufs_atomic_open() calling create, open and chmod. this is
1679+ an aufs user Pip Cet's approach
1680+ - calls aufs_create(), VFS finish_open() and notify_change().
1681+ - pass fake-mode to finish_open(), and then correct the mode by
1682+ notify_change().
1683+C. Extend aufs_open() to call branch fs's ->atomic_open()
1684+ - no aufs_atomic_open().
1685+ - aufs_lookup() registers the TID to an aufs internal object.
1686+ - aufs_create() does nothing when the matching TID is registered, but
1687+ registers the mode.
1688+ - aufs_open() calls branch fs's ->atomic_open() when the matching
1689+ TID is registered.
1690+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's
1691+ credential
1692+ - no aufs_atomic_open().
1693+ - aufs_create() registers the TID to an internal object. this info
1694+ represents "this process created this file just now."
1695+ - when aufs gets EACCES from branch fs's ->open(), then confirm the
1696+ registered TID and re-try open() with superuser's credential.
1697+
1698+Pros and cons for each approach.
1699+
1700+A.
1701+ - straightforward but highly depends upon VFS internal.
1702+ - the atomic behavaiour is kept.
1703+ - some of parameters such as nameidata are hard to reproduce for
1704+ branch fs.
1705+ - large overhead.
1706+B.
1707+ - easy to implement.
1708+ - the atomic behavaiour is lost.
1709+C.
1710+ - the atomic behavaiour is kept.
1711+ - dirty and tricky.
1712+ - VFS checks whether the file is created correctly after calling
1713+ ->create(), which means this approach doesn't work.
1714+D.
1715+ - easy to implement.
1716+ - the atomic behavaiour is lost.
1717+ - to open a file with superuser's credential and give it to a user
1718+ process is a bad idea, since the file object keeps the credential
1719+ in it. It may affect LSM or something. This approach doesn't work
1720+ either.
1721+
1722+The approach A is ideal, but it hard to implement. So here is a
1723+variation of A, which is to be implemented.
1724+
1725+A-1. Introduce aufs_atomic_open()
1726+ - calls branch fs ->atomic_open() if exists. otherwise calls
1727+ vfs_create() and finish_open().
1728+ - the demerit is that the several checks after branch fs
1729+ ->atomic_open() are lost. in the ordinary case, the checks are
1730+ done by VFS:do_last(), lookup_open() and atomic_open(). some can
1731+ be implemented in aufs, but not all I am afraid.
53392da6 1732diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
eca34b5c
AM
1733--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
1734+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2019-07-11 15:42:14.458904362 +0200
7e9cd9fe 1735@@ -0,0 +1,113 @@
53392da6 1736+
ba1aed25 1737+# Copyright (C) 2005-2019 Junjiro R. Okajima
53392da6
AM
1738+#
1739+# This program is free software; you can redistribute it and/or modify
1740+# it under the terms of the GNU General Public License as published by
1741+# the Free Software Foundation; either version 2 of the License, or
1742+# (at your option) any later version.
1743+#
1744+# This program is distributed in the hope that it will be useful,
1745+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1746+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1747+# GNU General Public License for more details.
1748+#
1749+# You should have received a copy of the GNU General Public License
523b37e3 1750+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1751+
1752+Lookup in a Branch
1753+----------------------------------------------------------------------
1754+Since aufs has a character of sub-VFS (see Introduction), it operates
7e9cd9fe
AM
1755+lookup for branches as VFS does. It may be a heavy work. But almost all
1756+lookup operation in aufs is the simplest case, ie. lookup only an entry
1757+directly connected to its parent. Digging down the directory hierarchy
1758+is unnecessary. VFS has a function lookup_one_len() for that use, and
1759+aufs calls it.
1760+
1761+When a branch is a remote filesystem, aufs basically relies upon its
53392da6
AM
1762+->d_revalidate(), also aufs forces the hardest revalidate tests for
1763+them.
1764+For d_revalidate, aufs implements three levels of revalidate tests. See
1765+"Revalidate Dentry and UDBA" in detail.
1766+
1767+
076b876e
AM
1768+Test Only the Highest One for the Directory Permission (dirperm1 option)
1769+----------------------------------------------------------------------
1770+Let's try case study.
1771+- aufs has two branches, upper readwrite and lower readonly.
1772+ /au = /rw + /ro
1773+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1774+- user invoked "chmod a+rx /au/dirA"
1775+- the internal copy-up is activated and "/rw/dirA" is created and its
7e9cd9fe 1776+ permission bits are set to world readable.
076b876e
AM
1777+- then "/au/dirA" becomes world readable?
1778+
1779+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1780+or it may be a natively readonly filesystem. If aufs respects the lower
1781+branch, it should not respond readdir request from other users. But user
1782+allowed it by chmod. Should really aufs rejects showing the entries
1783+under /ro/dirA?
1784+
7e9cd9fe
AM
1785+To be honest, I don't have a good solution for this case. So aufs
1786+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to
1787+users.
076b876e
AM
1788+When dirperm1 is specified, aufs checks only the highest one for the
1789+directory permission, and shows the entries. Otherwise, as usual, checks
1790+every dir existing on all branches and rejects the request.
1791+
1792+As a side effect, dirperm1 option improves the performance of aufs
1793+because the number of permission check is reduced when the number of
1794+branch is many.
1795+
1796+
53392da6
AM
1797+Revalidate Dentry and UDBA (User's Direct Branch Access)
1798+----------------------------------------------------------------------
1799+Generally VFS helpers re-validate a dentry as a part of lookup.
1800+0. digging down the directory hierarchy.
1801+1. lock the parent dir by its i_mutex.
1802+2. lookup the final (child) entry.
1803+3. revalidate it.
1804+4. call the actual operation (create, unlink, etc.)
1805+5. unlock the parent dir
1806+
1807+If the filesystem implements its ->d_revalidate() (step 3), then it is
1808+called. Actually aufs implements it and checks the dentry on a branch is
1809+still valid.
1810+But it is not enough. Because aufs has to release the lock for the
1811+parent dir on a branch at the end of ->lookup() (step 2) and
1812+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
1813+held by VFS.
1814+If the file on a branch is changed directly, eg. bypassing aufs, after
1815+aufs released the lock, then the subsequent operation may cause
1816+something unpleasant result.
1817+
1818+This situation is a result of VFS architecture, ->lookup() and
1819+->d_revalidate() is separated. But I never say it is wrong. It is a good
1820+design from VFS's point of view. It is just not suitable for sub-VFS
1821+character in aufs.
1822+
1823+Aufs supports such case by three level of revalidation which is
1824+selectable by user.
1825+1. Simple Revalidate
1826+ Addition to the native flow in VFS's, confirm the child-parent
1827+ relationship on the branch just after locking the parent dir on the
1828+ branch in the "actual operation" (step 4). When this validation
1829+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
1830+ checks the validation of the dentry on branches.
1831+2. Monitor Changes Internally by Inotify/Fsnotify
1832+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
1833+ the dentry on the branch, and returns EBUSY if it finds different
1834+ dentry.
1835+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
1836+ during it is in cache. When the event is notified, aufs registers a
1837+ function to kernel 'events' thread by schedule_work(). And the
1838+ function sets some special status to the cached aufs dentry and inode
1839+ private data. If they are not cached, then aufs has nothing to
1840+ do. When the same file is accessed through aufs (step 0-3) later,
1841+ aufs will detect the status and refresh all necessary data.
1842+ In this mode, aufs has to ignore the event which is fired by aufs
1843+ itself.
1844+3. No Extra Validation
1845+ This is the simplest test and doesn't add any additional revalidation
7e9cd9fe 1846+ test, and skip the revalidation in step 4. It is useful and improves
53392da6
AM
1847+ aufs performance when system surely hide the aufs branches from user,
1848+ by over-mounting something (or another method).
1849diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
eca34b5c
AM
1850--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
1851+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2019-07-11 15:42:14.458904362 +0200
7e9cd9fe 1852@@ -0,0 +1,74 @@
53392da6 1853+
ba1aed25 1854+# Copyright (C) 2005-2019 Junjiro R. Okajima
53392da6
AM
1855+#
1856+# This program is free software; you can redistribute it and/or modify
1857+# it under the terms of the GNU General Public License as published by
1858+# the Free Software Foundation; either version 2 of the License, or
1859+# (at your option) any later version.
1860+#
1861+# This program is distributed in the hope that it will be useful,
1862+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1863+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1864+# GNU General Public License for more details.
1865+#
1866+# You should have received a copy of the GNU General Public License
523b37e3 1867+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1868+
1869+Branch Manipulation
1870+
1871+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
1872+and changing its permission/attribute, there are a lot of works to do.
1873+
1874+
1875+Add a Branch
1876+----------------------------------------------------------------------
1877+o Confirm the adding dir exists outside of aufs, including loopback
7e9cd9fe 1878+ mount, and its various attributes.
53392da6
AM
1879+o Initialize the xino file and whiteout bases if necessary.
1880+ See struct.txt.
1881+
1882+o Check the owner/group/mode of the directory
1883+ When the owner/group/mode of the adding directory differs from the
1884+ existing branch, aufs issues a warning because it may impose a
1885+ security risk.
1886+ For example, when a upper writable branch has a world writable empty
1887+ top directory, a malicious user can create any files on the writable
1888+ branch directly, like copy-up and modify manually. If something like
1889+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
1890+ writable branch, and the writable branch is world-writable, then a
1891+ malicious guy may create /etc/passwd on the writable branch directly
1892+ and the infected file will be valid in aufs.
7e9cd9fe 1893+ I am afraid it can be a security issue, but aufs can do nothing except
53392da6
AM
1894+ producing a warning.
1895+
1896+
1897+Delete a Branch
1898+----------------------------------------------------------------------
1899+o Confirm the deleting branch is not busy
1900+ To be general, there is one merit to adopt "remount" interface to
1901+ manipulate branches. It is to discard caches. At deleting a branch,
1902+ aufs checks the still cached (and connected) dentries and inodes. If
1903+ there are any, then they are all in-use. An inode without its
1904+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
1905+
1906+ For the cached one, aufs checks whether the same named entry exists on
1907+ other branches.
1908+ If the cached one is a directory, because aufs provides a merged view
1909+ to users, as long as one dir is left on any branch aufs can show the
1910+ dir to users. In this case, the branch can be removed from aufs.
1911+ Otherwise aufs rejects deleting the branch.
1912+
1913+ If any file on the deleting branch is opened by aufs, then aufs
1914+ rejects deleting.
1915+
1916+
1917+Modify the Permission of a Branch
1918+----------------------------------------------------------------------
1919+o Re-initialize or remove the xino file and whiteout bases if necessary.
1920+ See struct.txt.
1921+
1922+o rw --> ro: Confirm the modifying branch is not busy
1923+ Aufs rejects the request if any of these conditions are true.
1924+ - a file on the branch is mmap-ed.
1925+ - a regular file on the branch is opened for write and there is no
1926+ same named entry on the upper branch.
1927diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
eca34b5c
AM
1928--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
1929+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2019-07-11 15:42:14.458904362 +0200
523b37e3 1930@@ -0,0 +1,64 @@
53392da6 1931+
ba1aed25 1932+# Copyright (C) 2005-2019 Junjiro R. Okajima
53392da6
AM
1933+#
1934+# This program is free software; you can redistribute it and/or modify
1935+# it under the terms of the GNU General Public License as published by
1936+# the Free Software Foundation; either version 2 of the License, or
1937+# (at your option) any later version.
1938+#
1939+# This program is distributed in the hope that it will be useful,
1940+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1941+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1942+# GNU General Public License for more details.
1943+#
1944+# You should have received a copy of the GNU General Public License
523b37e3 1945+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1946+
1947+Policies to Select One among Multiple Writable Branches
1948+----------------------------------------------------------------------
1949+When the number of writable branch is more than one, aufs has to decide
1950+the target branch for file creation or copy-up. By default, the highest
1951+writable branch which has the parent (or ancestor) dir of the target
1952+file is chosen (top-down-parent policy).
1953+By user's request, aufs implements some other policies to select the
7e9cd9fe
AM
1954+writable branch, for file creation several policies, round-robin,
1955+most-free-space, and other policies. For copy-up, top-down-parent,
1956+bottom-up-parent, bottom-up and others.
53392da6
AM
1957+
1958+As expected, the round-robin policy selects the branch in circular. When
1959+you have two writable branches and creates 10 new files, 5 files will be
1960+created for each branch. mkdir(2) systemcall is an exception. When you
1961+create 10 new directories, all will be created on the same branch.
1962+And the most-free-space policy selects the one which has most free
1963+space among the writable branches. The amount of free space will be
1964+checked by aufs internally, and users can specify its time interval.
1965+
1966+The policies for copy-up is more simple,
1967+top-down-parent is equivalent to the same named on in create policy,
1968+bottom-up-parent selects the writable branch where the parent dir
1969+exists and the nearest upper one from the copyup-source,
1970+bottom-up selects the nearest upper writable branch from the
1971+copyup-source, regardless the existence of the parent dir.
1972+
1973+There are some rules or exceptions to apply these policies.
1974+- If there is a readonly branch above the policy-selected branch and
1975+ the parent dir is marked as opaque (a variation of whiteout), or the
1976+ target (creating) file is whiteout-ed on the upper readonly branch,
1977+ then the result of the policy is ignored and the target file will be
1978+ created on the nearest upper writable branch than the readonly branch.
1979+- If there is a writable branch above the policy-selected branch and
1980+ the parent dir is marked as opaque or the target file is whiteouted
1981+ on the branch, then the result of the policy is ignored and the target
1982+ file will be created on the highest one among the upper writable
1983+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1984+ it as usual.
1985+- link(2) and rename(2) systemcalls are exceptions in every policy.
1986+ They try selecting the branch where the source exists as possible
1987+ since copyup a large file will take long time. If it can't be,
1988+ ie. the branch where the source exists is readonly, then they will
1989+ follow the copyup policy.
1990+- There is an exception for rename(2) when the target exists.
1991+ If the rename target exists, aufs compares the index of the branches
1992+ where the source and the target exists and selects the higher
1993+ one. If the selected branch is readonly, then aufs follows the
1994+ copyup policy.
8b6a4947 1995diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot linux/Documentation/filesystems/aufs/design/06dirren.dot
eca34b5c
AM
1996--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 01:00:00.000000000 +0100
1997+++ linux/Documentation/filesystems/aufs/design/06dirren.dot 2019-07-11 15:42:14.458904362 +0200
8b6a4947
AM
1998@@ -0,0 +1,31 @@
1999+
2000+// to view this graph, run dot(1) command in GRAPHVIZ.
2001+
2002+digraph G {
2003+node [shape=box];
2004+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"];
2005+
2006+node [shape=oval];
2007+
2008+aufs_rename -> whinfo [label="store/remove"];
2009+
2010+node [shape=oval];
2011+inode_list [label="h_inum list in branch\ncache"];
2012+
2013+node [shape=box];
2014+whinode [label="h_inum list file"];
2015+
2016+node [shape=oval];
2017+brmgmt [label="br_add/del/mod/umount"];
2018+
2019+brmgmt -> inode_list [label="create/remove"];
2020+brmgmt -> whinode [label="load/store"];
2021+
2022+inode_list -> whinode [style=dashed,dir=both];
2023+
2024+aufs_rename -> inode_list [label="add/del"];
2025+
2026+aufs_lookup -> inode_list [label="search"];
2027+
2028+aufs_lookup -> whinfo [label="load/remove"];
2029+}
2030diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt linux/Documentation/filesystems/aufs/design/06dirren.txt
eca34b5c
AM
2031--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 01:00:00.000000000 +0100
2032+++ linux/Documentation/filesystems/aufs/design/06dirren.txt 2019-07-11 15:42:14.458904362 +0200
8b6a4947
AM
2033@@ -0,0 +1,102 @@
2034+
ba1aed25 2035+# Copyright (C) 2017-2019 Junjiro R. Okajima
8b6a4947
AM
2036+#
2037+# This program is free software; you can redistribute it and/or modify
2038+# it under the terms of the GNU General Public License as published by
2039+# the Free Software Foundation; either version 2 of the License, or
2040+# (at your option) any later version.
2041+#
2042+# This program is distributed in the hope that it will be useful,
2043+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2044+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2045+# GNU General Public License for more details.
2046+#
2047+# You should have received a copy of the GNU General Public License
2048+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2049+
2050+Special handling for renaming a directory (DIRREN)
2051+----------------------------------------------------------------------
2052+First, let's assume we have a simple usecase.
2053+
2054+- /u = /rw + /ro
2055+- /rw/dirA exists
2056+- /ro/dirA and /ro/dirA/file exist too
2057+- there is no dirB on both branches
2058+- a user issues rename("dirA", "dirB")
2059+
2060+Now, what should aufs behave against this rename(2)?
2061+There are a few possible cases.
2062+
2063+A. returns EROFS.
2064+ since dirA exists on a readonly branch which cannot be renamed.
2065+B. returns EXDEV.
2066+ it is possible to copy-up dirA (only the dir itself), but the child
2067+ entries ("file" in this case) should not be. it must be a bad
2068+ approach to copy-up recursively.
2069+C. returns a success.
2070+ even the branch /ro is readonly, aufs tries renaming it. Obviously it
2071+ is a violation of aufs' policy.
2072+D. construct an extra information which indicates that /ro/dirA should
2073+ be handled as the name of dirB.
2074+ overlayfs has a similar feature called REDIRECT.
2075+
2076+Until now, aufs implements the case B only which returns EXDEV, and
2077+expects the userspace application behaves like mv(1) which tries
2078+issueing rename(2) recursively.
2079+
2080+A new aufs feature called DIRREN is introduced which implements the case
2081+D. There are several "extra information" added.
2082+
2083+1. detailed info per renamed directory
2084+ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX.<lower branch-id>
2085+2. the inode-number list of directories on a branch
2086+ path: /rw/dirB/$AUFS_WH_DR_BRHINO
2087+
2088+The filename of "detailed info per directory" represents the lower
2089+branch, and its format is
2090+- a type of the branch id
2091+ one of these.
2092+ + uuid (not implemented yet)
2093+ + fsid
2094+ + dev
2095+- the inode-number of the branch root dir
2096+
2097+And it contains these info in a single regular file.
2098+- magic number
2099+- branch's inode-number of the logically renamed dir
2100+- the name of the before-renamed dir
2101+
2102+The "detailed info per directory" file is created in aufs rename(2), and
2103+loaded in any lookup.
2104+The info is considered in lookup for the matching case only. Here
2105+"matching" means that the root of branch (in the info filename) is same
2106+to the current looking-up branch. After looking-up the before-renamed
2107+name, the inode-number is compared. And the matched dentry is used.
2108+
2109+The "inode-number list of directories" is a regular file which contains
2110+simply the inode-numbers on the branch. The file is created or updated
2111+in removing the branch, and loaded in adding the branch. Its lifetime is
2112+equal to the branch.
2113+The list is refered in lookup, and when the current target inode is
2114+found in the list, the aufs tries loading the "detailed info per
2115+directory" and get the changed and valid name of the dir.
2116+
2117+Theoretically these "extra informaiton" may be able to be put into XATTR
2118+in the dir inode. But aufs doesn't choose this way because
2119+1. XATTR may not be supported by the branch (or its configuration)
2120+2. XATTR may have its size limit.
2121+3. XATTR may be less easy to convert than a regular file, when the
2122+ format of the info is changed in the future.
2123+At the same time, I agree that the regular file approach is much slower
2124+than XATTR approach. So, in the future, aufs may take the XATTR or other
2125+better approach.
2126+
2127+This DIRREN feature is enabled by aufs configuration, and is activated
2128+by a new mount option.
2129+
2130+For the more complicated case, there is a work with UDBA option, which
2131+is to dected the direct access to the branches (by-passing aufs) and to
2132+maintain the cashes in aufs. Since a single cached aufs dentry may
2133+contains two names, before- and after-rename, the name comparision in
2134+UDBA handler may not work correctly. In this case, the behaviour will be
2135+equivalen to udba=reval case.
076b876e 2136diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linux/Documentation/filesystems/aufs/design/06fhsm.txt
eca34b5c
AM
2137--- /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100
2138+++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2019-07-11 15:42:14.458904362 +0200
076b876e
AM
2139@@ -0,0 +1,120 @@
2140+
ba1aed25 2141+# Copyright (C) 2011-2019 Junjiro R. Okajima
076b876e
AM
2142+#
2143+# This program is free software; you can redistribute it and/or modify
2144+# it under the terms of the GNU General Public License as published by
2145+# the Free Software Foundation; either version 2 of the License, or
2146+# (at your option) any later version.
2147+#
2148+# This program is distributed in the hope that it will be useful,
2149+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2150+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2151+# GNU General Public License for more details.
2152+#
2153+# You should have received a copy of the GNU General Public License
2154+# along with this program; if not, write to the Free Software
2155+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2156+
2157+
2158+File-based Hierarchical Storage Management (FHSM)
2159+----------------------------------------------------------------------
2160+Hierarchical Storage Management (or HSM) is a well-known feature in the
2161+storage world. Aufs provides this feature as file-based with multiple
7e9cd9fe 2162+writable branches, based upon the principle of "Colder, the Lower".
076b876e 2163+Here the word "colder" means that the less used files, and "lower" means
7e9cd9fe 2164+that the position in the order of the stacked branches vertically.
076b876e
AM
2165+These multiple writable branches are prioritized, ie. the topmost one
2166+should be the fastest drive and be used heavily.
2167+
2168+o Characters in aufs FHSM story
2169+- aufs itself and a new branch attribute.
2170+- a new ioctl interface to move-down and to establish a connection with
2171+ the daemon ("move-down" is a converse of "copy-up").
2172+- userspace tool and daemon.
2173+
2174+The userspace daemon establishes a connection with aufs and waits for
2175+the notification. The notified information is very similar to struct
2176+statfs containing the number of consumed blocks and inodes.
2177+When the consumed blocks/inodes of a branch exceeds the user-specified
2178+upper watermark, the daemon activates its move-down process until the
2179+consumed blocks/inodes reaches the user-specified lower watermark.
2180+
2181+The actual move-down is done by aufs based upon the request from
2182+user-space since we need to maintain the inode number and the internal
2183+pointer arrays in aufs.
2184+
2185+Currently aufs FHSM handles the regular files only. Additionally they
2186+must not be hard-linked nor pseudo-linked.
2187+
2188+
2189+o Cowork of aufs and the user-space daemon
2190+ During the userspace daemon established the connection, aufs sends a
2191+ small notification to it whenever aufs writes something into the
2192+ writable branch. But it may cost high since aufs issues statfs(2)
2193+ internally. So user can specify a new option to cache the
2194+ info. Actually the notification is controlled by these factors.
2195+ + the specified cache time.
2196+ + classified as "force" by aufs internally.
2197+ Until the specified time expires, aufs doesn't send the info
2198+ except the forced cases. When aufs decide forcing, the info is always
2199+ notified to userspace.
2200+ For example, the number of free inodes is generally large enough and
2201+ the shortage of it happens rarely. So aufs doesn't force the
2202+ notification when creating a new file, directory and others. This is
2203+ the typical case which aufs doesn't force.
2204+ When aufs writes the actual filedata and the files consumes any of new
2205+ blocks, the aufs forces notifying.
2206+
2207+
2208+o Interfaces in aufs
2209+- New branch attribute.
2210+ + fhsm
2211+ Specifies that the branch is managed by FHSM feature. In other word,
2212+ participant in the FHSM.
2213+ When nofhsm is set to the branch, it will not be the source/target
2214+ branch of the move-down operation. This attribute is set
2215+ independently from coo and moo attributes, and if you want full
2216+ FHSM, you should specify them as well.
2217+- New mount option.
2218+ + fhsm_sec
2219+ Specifies a second to suppress many less important info to be
2220+ notified.
2221+- New ioctl.
2222+ + AUFS_CTL_FHSM_FD
2223+ create a new file descriptor which userspace can read the notification
2224+ (a subset of struct statfs) from aufs.
2225+- Module parameter 'brs'
2226+ It has to be set to 1. Otherwise the new mount option 'fhsm' will not
2227+ be set.
2228+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs
2229+ When there are two or more branches with fhsm attributes,
2230+ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs
2231+ terminates it. As a result of remounting and branch-manipulation, the
2232+ number of branches with fhsm attribute can be one. In this case,
2233+ /sbin/mount.aufs will terminate the user-space daemon.
2234+
2235+
2236+Finally the operation is done as these steps in kernel-space.
2237+- make sure that,
2238+ + no one else is using the file.
2239+ + the file is not hard-linked.
2240+ + the file is not pseudo-linked.
2241+ + the file is a regular file.
2242+ + the parent dir is not opaqued.
2243+- find the target writable branch.
2244+- make sure the file is not whiteout-ed by the upper (than the target)
2245+ branch.
2246+- make the parent dir on the target branch.
2247+- mutex lock the inode on the branch.
2248+- unlink the whiteout on the target branch (if exists).
2249+- lookup and create the whiteout-ed temporary name on the target branch.
2250+- copy the file as the whiteout-ed temporary name on the target branch.
2251+- rename the whiteout-ed temporary name to the original name.
2252+- unlink the file on the source branch.
2253+- maintain the internal pointer array and the external inode number
2254+ table (XINO).
2255+- maintain the timestamps and other attributes of the parent dir and the
2256+ file.
2257+
2258+And of course, in every step, an error may happen. So the operation
2259+should restore the original file state after an error happens.
53392da6 2260diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
eca34b5c
AM
2261--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
2262+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2019-07-11 15:42:14.458904362 +0200
b912730e 2263@@ -0,0 +1,72 @@
53392da6 2264+
ba1aed25 2265+# Copyright (C) 2005-2019 Junjiro R. Okajima
53392da6
AM
2266+#
2267+# This program is free software; you can redistribute it and/or modify
2268+# it under the terms of the GNU General Public License as published by
2269+# the Free Software Foundation; either version 2 of the License, or
2270+# (at your option) any later version.
2271+#
2272+# This program is distributed in the hope that it will be useful,
2273+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2274+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2275+# GNU General Public License for more details.
2276+#
2277+# You should have received a copy of the GNU General Public License
523b37e3 2278+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2279+
2280+mmap(2) -- File Memory Mapping
2281+----------------------------------------------------------------------
2282+In aufs, the file-mapped pages are handled by a branch fs directly, no
2283+interaction with aufs. It means aufs_mmap() calls the branch fs's
2284+->mmap().
2285+This approach is simple and good, but there is one problem.
7e9cd9fe 2286+Under /proc, several entries show the mmapped files by its path (with
53392da6
AM
2287+device and inode number), and the printed path will be the path on the
2288+branch fs's instead of virtual aufs's.
2289+This is not a problem in most cases, but some utilities lsof(1) (and its
2290+user) may expect the path on aufs.
2291+
2292+To address this issue, aufs adds a new member called vm_prfile in struct
2293+vm_area_struct (and struct vm_region). The original vm_file points to
2294+the file on the branch fs in order to handle everything correctly as
2295+usual. The new vm_prfile points to a virtual file in aufs, and the
2296+show-functions in procfs refers to vm_prfile if it is set.
2297+Also we need to maintain several other places where touching vm_file
2298+such like
2299+- fork()/clone() copies vma and the reference count of vm_file is
2300+ incremented.
2301+- merging vma maintains the ref count too.
2302+
7e9cd9fe 2303+This is not a good approach. It just fakes the printed path. But it
53392da6
AM
2304+leaves all behaviour around f_mapping unchanged. This is surely an
2305+advantage.
2306+Actually aufs had adopted another complicated approach which calls
2307+generic_file_mmap() and handles struct vm_operations_struct. In this
2308+approach, aufs met a hard problem and I could not solve it without
2309+switching the approach.
b912730e
AM
2310+
2311+There may be one more another approach which is
2312+- bind-mount the branch-root onto the aufs-root internally
2313+- grab the new vfsmount (ie. struct mount)
2314+- lazy-umount the branch-root internally
2315+- in open(2) the aufs-file, open the branch-file with the hidden
2316+ vfsmount (instead of the original branch's vfsmount)
2317+- ideally this "bind-mount and lazy-umount" should be done atomically,
2318+ but it may be possible from userspace by the mount helper.
2319+
2320+Adding the internal hidden vfsmount and using it in opening a file, the
2321+file path under /proc will be printed correctly. This approach looks
2322+smarter, but is not possible I am afraid.
2323+- aufs-root may be bind-mount later. when it happens, another hidden
2324+ vfsmount will be required.
2325+- it is hard to get the chance to bind-mount and lazy-umount
2326+ + in kernel-space, FS can have vfsmount in open(2) via
2327+ file->f_path, and aufs can know its vfsmount. But several locks are
2328+ already acquired, and if aufs tries to bind-mount and lazy-umount
2329+ here, then it may cause a deadlock.
2330+ + in user-space, bind-mount doesn't invoke the mount helper.
2331+- since /proc shows dev and ino, aufs has to give vma these info. it
2332+ means a new member vm_prinode will be necessary. this is essentially
2333+ equivalent to vm_prfile described above.
2334+
2335+I have to give up this "looks-smater" approach.
c1595e42 2336diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt linux/Documentation/filesystems/aufs/design/06xattr.txt
eca34b5c
AM
2337--- /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 01:00:00.000000000 +0100
2338+++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2019-07-11 15:42:14.458904362 +0200
c1595e42
JR
2339@@ -0,0 +1,96 @@
2340+
ba1aed25 2341+# Copyright (C) 2014-2019 Junjiro R. Okajima
c1595e42
JR
2342+#
2343+# This program is free software; you can redistribute it and/or modify
2344+# it under the terms of the GNU General Public License as published by
2345+# the Free Software Foundation; either version 2 of the License, or
2346+# (at your option) any later version.
2347+#
2348+# This program is distributed in the hope that it will be useful,
2349+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2350+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2351+# GNU General Public License for more details.
2352+#
2353+# You should have received a copy of the GNU General Public License
2354+# along with this program; if not, write to the Free Software
2355+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2356+
2357+
2358+Listing XATTR/EA and getting the value
2359+----------------------------------------------------------------------
2360+For the inode standard attributes (owner, group, timestamps, etc.), aufs
2361+shows the values from the topmost existing file. This behaviour is good
7e9cd9fe 2362+for the non-dir entries since the bahaviour exactly matches the shown
c1595e42
JR
2363+information. But for the directories, aufs considers all the same named
2364+entries on the lower branches. Which means, if one of the lower entry
2365+rejects readdir call, then aufs returns an error even if the topmost
2366+entry allows it. This behaviour is necessary to respect the branch fs's
2367+security, but can make users confused since the user-visible standard
2368+attributes don't match the behaviour.
2369+To address this issue, aufs has a mount option called dirperm1 which
2370+checks the permission for the topmost entry only, and ignores the lower
2371+entry's permission.
2372+
2373+A similar issue can happen around XATTR.
2374+getxattr(2) and listxattr(2) families behave as if dirperm1 option is
7e9cd9fe
AM
2375+always set. Otherwise these very unpleasant situation would happen.
2376+- listxattr(2) may return the duplicated entries.
c1595e42
JR
2377+- users may not be able to remove or reset the XATTR forever,
2378+
2379+
2380+XATTR/EA support in the internal (copy,move)-(up,down)
2381+----------------------------------------------------------------------
7e9cd9fe 2382+Generally the extended attributes of inode are categorized as these.
c1595e42
JR
2383+- "security" for LSM and capability.
2384+- "system" for posix ACL, 'acl' mount option is required for the branch
2385+ fs generally.
2386+- "trusted" for userspace, CAP_SYS_ADMIN is required.
2387+- "user" for userspace, 'user_xattr' mount option is required for the
2388+ branch fs generally.
2389+
2390+Moreover there are some other categories. Aufs handles these rather
2391+unpopular categories as the ordinary ones, ie. there is no special
2392+condition nor exception.
2393+
2394+In copy-up, the support for XATTR on the dst branch may differ from the
2395+src branch. In this case, the copy-up operation will get an error and
7e9cd9fe
AM
2396+the original user operation which triggered the copy-up will fail. It
2397+can happen that even all copy-up will fail.
c1595e42
JR
2398+When both of src and dst branches support XATTR and if an error occurs
2399+during copying XATTR, then the copy-up should fail obviously. That is a
2400+good reason and aufs should return an error to userspace. But when only
7e9cd9fe 2401+the src branch support that XATTR, aufs should not return an error.
c1595e42
JR
2402+For example, the src branch supports ACL but the dst branch doesn't
2403+because the dst branch may natively un-support it or temporary
2404+un-support it due to "noacl" mount option. Of course, the dst branch fs
2405+may NOT return an error even if the XATTR is not supported. It is
2406+totally up to the branch fs.
2407+
2408+Anyway when the aufs internal copy-up gets an error from the dst branch
2409+fs, then aufs tries removing the just copied entry and returns the error
2410+to the userspace. The worst case of this situation will be all copy-up
2411+will fail.
2412+
2413+For the copy-up operation, there two basic approaches.
2414+- copy the specified XATTR only (by category above), and return the
7e9cd9fe 2415+ error unconditionally if it happens.
c1595e42
JR
2416+- copy all XATTR, and ignore the error on the specified category only.
2417+
2418+In order to support XATTR and to implement the correct behaviour, aufs
7e9cd9fe
AM
2419+chooses the latter approach and introduces some new branch attributes,
2420+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth".
c1595e42 2421+They correspond to the XATTR namespaces (see above). Additionally, to be
7e9cd9fe
AM
2422+convenient, "icex" is also provided which means all "icex*" attributes
2423+are set (here the word "icex" stands for "ignore copy-error on XATTR").
c1595e42
JR
2424+
2425+The meaning of these attributes is to ignore the error from setting
2426+XATTR on that branch.
2427+Note that aufs tries copying all XATTR unconditionally, and ignores the
2428+error from the dst branch according to the specified attributes.
2429+
2430+Some XATTR may have its default value. The default value may come from
2431+the parent dir or the environment. If the default value is set at the
2432+file creating-time, it will be overwritten by copy-up.
2433+Some contradiction may happen I am afraid.
2434+Do we need another attribute to stop copying XATTR? I am unsure. For
2435+now, aufs implements the branch attributes to ignore the error.
53392da6 2436diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
eca34b5c
AM
2437--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
2438+++ linux/Documentation/filesystems/aufs/design/07export.txt 2019-07-11 15:42:14.458904362 +0200
523b37e3 2439@@ -0,0 +1,58 @@
53392da6 2440+
ba1aed25 2441+# Copyright (C) 2005-2019 Junjiro R. Okajima
53392da6
AM
2442+#
2443+# This program is free software; you can redistribute it and/or modify
2444+# it under the terms of the GNU General Public License as published by
2445+# the Free Software Foundation; either version 2 of the License, or
2446+# (at your option) any later version.
2447+#
2448+# This program is distributed in the hope that it will be useful,
2449+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2450+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2451+# GNU General Public License for more details.
2452+#
2453+# You should have received a copy of the GNU General Public License
523b37e3 2454+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2455+
2456+Export Aufs via NFS
2457+----------------------------------------------------------------------
2458+Here is an approach.
2459+- like xino/xib, add a new file 'xigen' which stores aufs inode
2460+ generation.
2461+- iget_locked(): initialize aufs inode generation for a new inode, and
2462+ store it in xigen file.
2463+- destroy_inode(): increment aufs inode generation and store it in xigen
2464+ file. it is necessary even if it is not unlinked, because any data of
2465+ inode may be changed by UDBA.
2466+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
2467+ build file handle by
2468+ + branch id (4 bytes)
2469+ + superblock generation (4 bytes)
2470+ + inode number (4 or 8 bytes)
2471+ + parent dir inode number (4 or 8 bytes)
2472+ + inode generation (4 bytes))
2473+ + return value of exportfs_encode_fh() for the parent on a branch (4
2474+ bytes)
2475+ + file handle for a branch (by exportfs_encode_fh())
2476+- fh_to_dentry():
2477+ + find the index of a branch from its id in handle, and check it is
2478+ still exist in aufs.
2479+ + 1st level: get the inode number from handle and search it in cache.
7e9cd9fe
AM
2480+ + 2nd level: if not found in cache, get the parent inode number from
2481+ the handle and search it in cache. and then open the found parent
2482+ dir, find the matching inode number by vfs_readdir() and get its
2483+ name, and call lookup_one_len() for the target dentry.
53392da6
AM
2484+ + 3rd level: if the parent dir is not cached, call
2485+ exportfs_decode_fh() for a branch and get the parent on a branch,
2486+ build a pathname of it, convert it a pathname in aufs, call
2487+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
2488+ the 2nd level.
2489+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
2490+ for every branch, but not itself. to get this, (currently) aufs
2491+ searches in current->nsproxy->mnt_ns list. it may not be a good
2492+ idea, but I didn't get other approach.
2493+ + test the generation of the gotten inode.
2494+- every inode operation: they may get EBUSY due to UDBA. in this case,
2495+ convert it into ESTALE for NFSD.
2496+- readdir(): call lockdep_on/off() because filldir in NFSD calls
2497+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
2498diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
eca34b5c
AM
2499--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
2500+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2019-07-11 15:42:14.458904362 +0200
523b37e3 2501@@ -0,0 +1,52 @@
53392da6 2502+
ba1aed25 2503+# Copyright (C) 2005-2019 Junjiro R. Okajima
53392da6
AM
2504+#
2505+# This program is free software; you can redistribute it and/or modify
2506+# it under the terms of the GNU General Public License as published by
2507+# the Free Software Foundation; either version 2 of the License, or
2508+# (at your option) any later version.
2509+#
2510+# This program is distributed in the hope that it will be useful,
2511+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2512+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2513+# GNU General Public License for more details.
2514+#
2515+# You should have received a copy of the GNU General Public License
523b37e3 2516+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2517+
2518+Show Whiteout Mode (shwh)
2519+----------------------------------------------------------------------
2520+Generally aufs hides the name of whiteouts. But in some cases, to show
2521+them is very useful for users. For instance, creating a new middle layer
2522+(branch) by merging existing layers.
2523+
2524+(borrowing aufs1 HOW-TO from a user, Michael Towers)
2525+When you have three branches,
2526+- Bottom: 'system', squashfs (underlying base system), read-only
2527+- Middle: 'mods', squashfs, read-only
2528+- Top: 'overlay', ram (tmpfs), read-write
2529+
2530+The top layer is loaded at boot time and saved at shutdown, to preserve
2531+the changes made to the system during the session.
2532+When larger changes have been made, or smaller changes have accumulated,
2533+the size of the saved top layer data grows. At this point, it would be
2534+nice to be able to merge the two overlay branches ('mods' and 'overlay')
2535+and rewrite the 'mods' squashfs, clearing the top layer and thus
2536+restoring save and load speed.
2537+
2538+This merging is simplified by the use of another aufs mount, of just the
2539+two overlay branches using the 'shwh' option.
2540+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
2541+ aufs /livesys/merge_union
2542+
2543+A merged view of these two branches is then available at
2544+/livesys/merge_union, and the new feature is that the whiteouts are
2545+visible!
2546+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
2547+writing to all branches. Also the default mode for all branches is 'ro'.
2548+It is now possible to save the combined contents of the two overlay
2549+branches to a new squashfs, e.g.:
2550+# mksquashfs /livesys/merge_union /path/to/newmods.squash
2551+
2552+This new squashfs archive can be stored on the boot device and the
2553+initramfs will use it to replace the old one at the next boot.
2554diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
eca34b5c
AM
2555--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
2556+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2019-07-11 15:42:14.458904362 +0200
7e9cd9fe 2557@@ -0,0 +1,47 @@
53392da6 2558+
ba1aed25 2559+# Copyright (C) 2010-2019 Junjiro R. Okajima
53392da6
AM
2560+#
2561+# This program is free software; you can redistribute it and/or modify
2562+# it under the terms of the GNU General Public License as published by
2563+# the Free Software Foundation; either version 2 of the License, or
2564+# (at your option) any later version.
2565+#
2566+# This program is distributed in the hope that it will be useful,
2567+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2568+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2569+# GNU General Public License for more details.
2570+#
2571+# You should have received a copy of the GNU General Public License
523b37e3 2572+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2573+
2574+Dynamically customizable FS operations
2575+----------------------------------------------------------------------
2576+Generally FS operations (struct inode_operations, struct
2577+address_space_operations, struct file_operations, etc.) are defined as
2578+"static const", but it never means that FS have only one set of
2579+operation. Some FS have multiple sets of them. For instance, ext2 has
2580+three sets, one for XIP, for NOBH, and for normal.
2581+Since aufs overrides and redirects these operations, sometimes aufs has
7e9cd9fe 2582+to change its behaviour according to the branch FS type. More importantly
53392da6
AM
2583+VFS acts differently if a function (member in the struct) is set or
2584+not. It means aufs should have several sets of operations and select one
2585+among them according to the branch FS definition.
2586+
7e9cd9fe 2587+In order to solve this problem and not to affect the behaviour of VFS,
53392da6 2588+aufs defines these operations dynamically. For instance, aufs defines
7e9cd9fe
AM
2589+dummy direct_IO function for struct address_space_operations, but it may
2590+not be set to the address_space_operations actually. When the branch FS
2591+doesn't have it, aufs doesn't set it to its address_space_operations
2592+while the function definition itself is still alive. So the behaviour
2593+itself will not change, and it will return an error when direct_IO is
2594+not set.
53392da6
AM
2595+
2596+The lifetime of these dynamically generated operation object is
2597+maintained by aufs branch object. When the branch is removed from aufs,
2598+the reference counter of the object is decremented. When it reaches
2599+zero, the dynamically generated operation object will be freed.
2600+
7e9cd9fe
AM
2601+This approach is designed to support AIO (io_submit), Direct I/O and
2602+XIP (DAX) mainly.
2603+Currently this approach is applied to address_space_operations for
2604+regular files only.
53392da6 2605diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
eca34b5c
AM
2606--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
2607+++ linux/Documentation/filesystems/aufs/README 2019-07-11 15:42:14.455570938 +0200
fbc438ed 2608@@ -0,0 +1,399 @@
53392da6 2609+
fbc438ed 2610+Aufs5 -- advanced multi layered unification filesystem version 5.x
53392da6
AM
2611+http://aufs.sf.net
2612+Junjiro R. Okajima
2613+
2614+
2615+0. Introduction
2616+----------------------------------------
2617+In the early days, aufs was entirely re-designed and re-implemented
7e9cd9fe 2618+Unionfs Version 1.x series. Adding many original ideas, approaches,
fbc438ed 2619+improvements and implementations, it became totally different from
53392da6 2620+Unionfs while keeping the basic features.
fbc438ed 2621+Later, Unionfs Version 2.x series began taking some of the same
53392da6 2622+approaches to aufs1's.
fbc438ed 2623+Unionfs was being developed by Professor Erez Zadok at Stony Brook
53392da6
AM
2624+University and his team.
2625+
fbc438ed
JR
2626+Aufs5 supports linux-v5.0 and later, If you want older kernel version
2627+support,
2628+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git
2629+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git
2630+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git
2631+ or aufs1 from CVS on SourceForge.
53392da6
AM
2632+
2633+Note: it becomes clear that "Aufs was rejected. Let's give it up."
38d290e6
JR
2634+ According to Christoph Hellwig, linux rejects all union-type
2635+ filesystems but UnionMount.
53392da6
AM
2636+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
2637+
38d290e6
JR
2638+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and
2639+ UnionMount, and he pointed out an issue around a directory mutex
2640+ lock and aufs addressed it. But it is still unsure whether aufs will
2641+ be merged (or any other union solution).
076b876e 2642+<http://marc.info/?l=linux-kernel&m=136312705029295&w=1>
38d290e6 2643+
53392da6
AM
2644+
2645+1. Features
2646+----------------------------------------
2647+- unite several directories into a single virtual filesystem. The member
2648+ directory is called as a branch.
2649+- you can specify the permission flags to the branch, which are 'readonly',
2650+ 'readwrite' and 'whiteout-able.'
2651+- by upper writable branch, internal copyup and whiteout, files/dirs on
2652+ readonly branch are modifiable logically.
2653+- dynamic branch manipulation, add, del.
2654+- etc...
2655+
7e9cd9fe
AM
2656+Also there are many enhancements in aufs, such as:
2657+- test only the highest one for the directory permission (dirperm1)
2658+- copyup on open (coo=)
2659+- 'move' policy for copy-up between two writable branches, after
2660+ checking free space.
2661+- xattr, acl
53392da6
AM
2662+- readdir(3) in userspace.
2663+- keep inode number by external inode number table
2664+- keep the timestamps of file/dir in internal copyup operation
2665+- seekable directory, supporting NFS readdir.
2666+- whiteout is hardlinked in order to reduce the consumption of inodes
2667+ on branch
2668+- do not copyup, nor create a whiteout when it is unnecessary
2669+- revert a single systemcall when an error occurs in aufs
2670+- remount interface instead of ioctl
2671+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
2672+- loopback mounted filesystem as a branch
2673+- kernel thread for removing the dir who has a plenty of whiteouts
2674+- support copyup sparse file (a file which has a 'hole' in it)
2675+- default permission flags for branches
2676+- selectable permission flags for ro branch, whether whiteout can
2677+ exist or not
2678+- export via NFS.
2679+- support <sysfs>/fs/aufs and <debugfs>/aufs.
2680+- support multiple writable branches, some policies to select one
2681+ among multiple writable branches.
2682+- a new semantics for link(2) and rename(2) to support multiple
2683+ writable branches.
2684+- no glibc changes are required.
2685+- pseudo hardlink (hardlink over branches)
2686+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
2687+ including NFS or remote filesystem branch.
2688+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
2689+- and more...
2690+
fbc438ed 2691+Currently these features are dropped temporary from aufs5.
53392da6 2692+See design/08plan.txt in detail.
53392da6
AM
2693+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
2694+ (robr)
2695+- statistics of aufs thread (/sys/fs/aufs/stat)
53392da6
AM
2696+
2697+Features or just an idea in the future (see also design/*.txt),
2698+- reorder the branch index without del/re-add.
2699+- permanent xino files for NFSD
2700+- an option for refreshing the opened files after add/del branches
53392da6
AM
2701+- light version, without branch manipulation. (unnecessary?)
2702+- copyup in userspace
2703+- inotify in userspace
2704+- readv/writev
53392da6
AM
2705+
2706+
2707+2. Download
2708+----------------------------------------
fbc438ed
JR
2709+There are three GIT trees for aufs5, aufs5-linux.git,
2710+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in
1e00d052 2711+"aufs-util.git."
fbc438ed
JR
2712+While the aufs-util is always necessary, you need either of aufs5-linux
2713+or aufs5-standalone.
1e00d052 2714+
fbc438ed 2715+The aufs5-linux tree includes the whole linux mainline GIT tree,
1e00d052
AM
2716+git://git.kernel.org/.../torvalds/linux.git.
2717+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
fbc438ed 2718+build aufs5 as an external kernel module.
2000de60 2719+Several extra patches are not included in this tree. Only
fbc438ed 2720+aufs5-standalone tree contains them. They are described in the later
2000de60 2721+section "Configuration and Compilation."
1e00d052 2722+
fbc438ed 2723+On the other hand, the aufs5-standalone tree has only aufs source files
53392da6 2724+and necessary patches, and you can select CONFIG_AUFS_FS=m.
2000de60 2725+But you need to apply all aufs patches manually.
53392da6 2726+
fbc438ed
JR
2727+You will find GIT branches whose name is in form of "aufs5.x" where "x"
2728+represents the linux kernel version, "linux-5.x". For instance,
2729+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use
2730+"aufs5.x-rcN" branch.
1e00d052 2731+
fbc438ed 2732+o aufs5-linux tree
1e00d052 2733+$ git clone --reference /your/linux/git/tree \
fbc438ed 2734+ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git
1e00d052 2735+- if you don't have linux GIT tree, then remove "--reference ..."
fbc438ed
JR
2736+$ cd aufs5-linux.git
2737+$ git checkout origin/aufs5.0
53392da6 2738+
2000de60
JR
2739+Or You may want to directly git-pull aufs into your linux GIT tree, and
2740+leave the patch-work to GIT.
2741+$ cd /your/linux/git/tree
fbc438ed
JR
2742+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git
2743+$ git fetch aufs5
2744+$ git checkout -b my5.0 v5.0
5527c038 2745+$ (add your local change...)
fbc438ed
JR
2746+$ git pull aufs5 aufs5.0
2747+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch.
2000de60 2748+- you may need to solve some conflicts between your_changes and
fbc438ed
JR
2749+ aufs5.0. in this case, git-rerere is recommended so that you can
2750+ solve the similar conflicts automatically when you upgrade to 5.1 or
2000de60
JR
2751+ later in the future.
2752+
fbc438ed
JR
2753+o aufs5-standalone tree
2754+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git
2755+$ cd aufs5-standalone.git
2756+$ git checkout origin/aufs5.0
53392da6
AM
2757+
2758+o aufs-util tree
5527c038
JR
2759+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git
2760+- note that the public aufs-util.git is on SourceForge instead of
2761+ GitHUB.
53392da6 2762+$ cd aufs-util.git
fbc438ed 2763+$ git checkout origin/aufs5.0
53392da6 2764+
fbc438ed
JR
2765+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY.
2766+The minor version number, 'x' in '5.x', of aufs may not always
9dbd164d
AM
2767+follow the minor version number of the kernel.
2768+Because changes in the kernel that cause the use of a new
2769+minor version number do not always require changes to aufs-util.
2770+
2771+Since aufs-util has its own minor version number, you may not be
2772+able to find a GIT branch in aufs-util for your kernel's
2773+exact minor version number.
2774+In this case, you should git-checkout the branch for the
53392da6 2775+nearest lower number.
9dbd164d
AM
2776+
2777+For (an unreleased) example:
fbc438ed
JR
2778+If you are using "linux-5.10" and the "aufs5.10" branch
2779+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8"
9dbd164d
AM
2780+or something numerically smaller is the branch for your kernel.
2781+
53392da6
AM
2782+Also you can view all branches by
2783+ $ git branch -a
2784+
2785+
2786+3. Configuration and Compilation
2787+----------------------------------------
2788+Make sure you have git-checkout'ed the correct branch.
2789+
fbc438ed 2790+For aufs5-linux tree,
c06a8ce3 2791+- enable CONFIG_AUFS_FS.
1e00d052
AM
2792+- set other aufs configurations if necessary.
2793+
fbc438ed 2794+For aufs5-standalone tree,
53392da6
AM
2795+There are several ways to build.
2796+
2797+1.
fbc438ed
JR
2798+- apply ./aufs5-kbuild.patch to your kernel source files.
2799+- apply ./aufs5-base.patch too.
2800+- apply ./aufs5-mmap.patch too.
2801+- apply ./aufs5-standalone.patch too, if you have a plan to set
2802+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch.
537831f9
AM
2803+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your
2804+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild.
c06a8ce3 2805+- enable CONFIG_AUFS_FS, you can select either
53392da6
AM
2806+ =m or =y.
2807+- and build your kernel as usual.
2808+- install the built kernel.
7eafdf33
AM
2809+- install the header files too by "make headers_install" to the
2810+ directory where you specify. By default, it is $PWD/usr.
b4510431 2811+ "make help" shows a brief note for headers_install.
53392da6
AM
2812+- and reboot your system.
2813+
2814+2.
2815+- module only (CONFIG_AUFS_FS=m).
fbc438ed
JR
2816+- apply ./aufs5-base.patch to your kernel source files.
2817+- apply ./aufs5-mmap.patch too.
2818+- apply ./aufs5-standalone.patch too.
53392da6
AM
2819+- build your kernel, don't forget "make headers_install", and reboot.
2820+- edit ./config.mk and set other aufs configurations if necessary.
b4510431 2821+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
53392da6
AM
2822+ every aufs configurations.
2823+- build the module by simple "make".
2824+- you can specify ${KDIR} make variable which points to your kernel
2825+ source tree.
2826+- install the files
2827+ + run "make install" to install the aufs module, or copy the built
b4510431
AM
2828+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
2829+ + run "make install_headers" (instead of headers_install) to install
2830+ the modified aufs header file (you can specify DESTDIR which is
2831+ available in aufs standalone version's Makefile only), or copy
2832+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
2833+ you like manually. By default, the target directory is $PWD/usr.
fbc438ed 2834+- no need to apply aufs5-kbuild.patch, nor copying source files to your
53392da6
AM
2835+ kernel source tree.
2836+
b4510431 2837+Note: The header file aufs_type.h is necessary to build aufs-util
53392da6
AM
2838+ as well as "make headers_install" in the kernel source tree.
2839+ headers_install is subject to be forgotten, but it is essentially
2840+ necessary, not only for building aufs-util.
2841+ You may not meet problems without headers_install in some older
2842+ version though.
2843+
2844+And then,
2845+- read README in aufs-util, build and install it
9dbd164d
AM
2846+- note that your distribution may contain an obsoleted version of
2847+ aufs_type.h in /usr/include/linux or something. When you build aufs
2848+ utilities, make sure that your compiler refers the correct aufs header
2849+ file which is built by "make headers_install."
53392da6
AM
2850+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
2851+ then run "make install_ulib" too. And refer to the aufs manual in
2852+ detail.
2853+
fbc438ed 2854+There several other patches in aufs5-standalone.git. They are all
38d290e6 2855+optional. When you meet some problems, they will help you.
fbc438ed 2856+- aufs5-loopback.patch
38d290e6
JR
2857+ Supports a nested loopback mount in a branch-fs. This patch is
2858+ unnecessary until aufs produces a message like "you may want to try
2859+ another patch for loopback file".
83b672a5
AM
2860+- proc_mounts.patch
2861+ When there are many mountpoints and many mount(2)/umount(2) are
2862+ running, then /proc/mounts may not show the all mountpoints. This
2863+ patch makes /proc/mounts always show the full mountpoints list.
2864+ If you don't want to apply this patch and meet such problem, then you
2865+ need to increase the value of 'ProcMounts_Times' make-variable in
2866+ aufs-util.git as a second best solution.
38d290e6
JR
2867+- vfs-ino.patch
2868+ Modifies a system global kernel internal function get_next_ino() in
2869+ order to stop assigning 0 for an inode-number. Not directly related to
2870+ aufs, but recommended generally.
2871+- tmpfs-idr.patch
2872+ Keeps the tmpfs inode number as the lowest value. Effective to reduce
2873+ the size of aufs XINO files for tmpfs branch. Also it prevents the
2874+ duplication of inode number, which is important for backup tools and
2875+ other utilities. When you find aufs XINO files for tmpfs branch
2876+ growing too much, try this patch.
be52b249
AM
2877+- lockdep-debug.patch
2878+ Because aufs is not only an ordinary filesystem (callee of VFS), but
2879+ also a caller of VFS functions for branch filesystems, subclassing of
2880+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging
2881+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will
2882+ need to apply this debug patch to expand several constant values.
fbc438ed 2883+ If don't know what LOCKDEP is, then you don't have apply this patch.
38d290e6 2884+
53392da6
AM
2885+
2886+4. Usage
2887+----------------------------------------
2888+At first, make sure aufs-util are installed, and please read the aufs
2889+manual, aufs.5 in aufs-util.git tree.
2890+$ man -l aufs.5
2891+
2892+And then,
2893+$ mkdir /tmp/rw /tmp/aufs
2894+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
2895+
2896+Here is another example. The result is equivalent.
2897+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
2898+ Or
2899+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
2900+# mount -o remount,append:${HOME} /tmp/aufs
2901+
2902+Then, you can see whole tree of your home dir through /tmp/aufs. If
2903+you modify a file under /tmp/aufs, the one on your home directory is
2904+not affected, instead the same named file will be newly created under
2905+/tmp/rw. And all of your modification to a file will be applied to
2906+the one under /tmp/rw. This is called the file based Copy on Write
2907+(COW) method.
2908+Aufs mount options are described in aufs.5.
2909+If you run chroot or something and make your aufs as a root directory,
2910+then you need to customize the shutdown script. See the aufs manual in
2911+detail.
2912+
2913+Additionally, there are some sample usages of aufs which are a
2914+diskless system with network booting, and LiveCD over NFS.
2915+See sample dir in CVS tree on SourceForge.
2916+
2917+
2918+5. Contact
2919+----------------------------------------
2920+When you have any problems or strange behaviour in aufs, please let me
2921+know with:
2922+- /proc/mounts (instead of the output of mount(8))
2923+- /sys/module/aufs/*
2924+- /sys/fs/aufs/* (if you have them)
2925+- /debug/aufs/* (if you have them)
2926+- linux kernel version
2927+ if your kernel is not plain, for example modified by distributor,
2928+ the url where i can download its source is necessary too.
2929+- aufs version which was printed at loading the module or booting the
2930+ system, instead of the date you downloaded.
2931+- configuration (define/undefine CONFIG_AUFS_xxx)
2932+- kernel configuration or /proc/config.gz (if you have it)
2933+- behaviour which you think to be incorrect
2934+- actual operation, reproducible one is better
2935+- mailto: aufs-users at lists.sourceforge.net
2936+
2937+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
2938+and Feature Requests) on SourceForge. Please join and write to
2939+aufs-users ML.
2940+
2941+
2942+6. Acknowledgements
2943+----------------------------------------
2944+Thanks to everyone who have tried and are using aufs, whoever
2945+have reported a bug or any feedback.
2946+
2947+Especially donators:
2948+Tomas Matejicek(slax.org) made a donation (much more than once).
2949+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
2950+ scripts) is making "doubling" donations.
2951+ Unfortunately I cannot list all of the donators, but I really
b4510431 2952+ appreciate.
53392da6
AM
2953+ It ends Aug 2010, but the ordinary donation URL is still available.
2954+ <http://sourceforge.net/donate/index.php?group_id=167503>
2955+Dai Itasaka made a donation (2007/8).
2956+Chuck Smith made a donation (2008/4, 10 and 12).
2957+Henk Schoneveld made a donation (2008/9).
2958+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
2959+Francois Dupoux made a donation (2008/11).
2960+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
2961+ aufs2 GIT tree (2009/2).
2962+William Grant made a donation (2009/3).
2963+Patrick Lane made a donation (2009/4).
2964+The Mail Archive (mail-archive.com) made donations (2009/5).
2965+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
2966+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
2967+Pavel Pronskiy made a donation (2011/2).
2968+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
2969+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
537831f9
AM
2970+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and
2971+11).
1e00d052 2972+Sam Liddicott made a donation (2011/9).
86dc4139
AM
2973+Era Scarecrow made a donation (2013/4).
2974+Bor Ratajc made a donation (2013/4).
2975+Alessandro Gorreta made a donation (2013/4).
2976+POIRETTE Marc made a donation (2013/4).
2977+Alessandro Gorreta made a donation (2013/4).
2978+lauri kasvandik made a donation (2013/5).
392086de 2979+"pemasu from Finland" made a donation (2013/7).
523b37e3
AM
2980+The Parted Magic Project made a donation (2013/9 and 11).
2981+Pavel Barta made a donation (2013/10).
38d290e6 2982+Nikolay Pertsev made a donation (2014/5).
c2c0f25c 2983+James B made a donation (2014/7 and 2015/7).
076b876e 2984+Stefano Di Biase made a donation (2014/8).
2000de60 2985+Daniel Epellei made a donation (2015/1).
c4adf169 2986+OmegaPhil made a donation (2016/1, 2018/4).
5afbbe0d 2987+Tomasz Szewczyk made a donation (2016/4).
f2c43d5f 2988+James Burry made a donation (2016/12).
acd2b654 2989+Carsten Rose made a donation (2018/9).
9f237c51 2990+Porteus Kiosk made a donation (2018/10).
53392da6
AM
2991+
2992+Thank you very much.
2993+Donations are always, including future donations, very important and
2994+helpful for me to keep on developing aufs.
2995+
2996+
2997+7.
2998+----------------------------------------
2999+If you are an experienced user, no explanation is needed. Aufs is
3000+just a linux filesystem.
3001+
3002+
3003+Enjoy!
3004+
3005+# Local variables: ;
3006+# mode: text;
3007+# End: ;
7f207e10 3008diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
eca34b5c
AM
3009--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
3010+++ linux/fs/aufs/aufs.h 2019-07-11 15:42:14.462237786 +0200
acd2b654 3011@@ -0,0 +1,62 @@
062440b3 3012+/* SPDX-License-Identifier: GPL-2.0 */
7f207e10 3013+/*
ba1aed25 3014+ * Copyright (C) 2005-2019 Junjiro R. Okajima
7f207e10
AM
3015+ *
3016+ * This program, aufs is free software; you can redistribute it and/or modify
3017+ * it under the terms of the GNU General Public License as published by
3018+ * the Free Software Foundation; either version 2 of the License, or
3019+ * (at your option) any later version.
3020+ *
3021+ * This program is distributed in the hope that it will be useful,
3022+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3023+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3024+ * GNU General Public License for more details.
3025+ *
3026+ * You should have received a copy of the GNU General Public License
523b37e3 3027+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
3028+ */
3029+
3030+/*
3031+ * all header files
3032+ */
3033+
3034+#ifndef __AUFS_H__
3035+#define __AUFS_H__
3036+
3037+#ifdef __KERNEL__
3038+
3039+#define AuStub(type, name, body, ...) \
3040+ static inline type name(__VA_ARGS__) { body; }
3041+
3042+#define AuStubVoid(name, ...) \
3043+ AuStub(void, name, , __VA_ARGS__)
3044+#define AuStubInt0(name, ...) \
3045+ AuStub(int, name, return 0, __VA_ARGS__)
3046+
3047+#include "debug.h"
3048+
3049+#include "branch.h"
3050+#include "cpup.h"
3051+#include "dcsub.h"
3052+#include "dbgaufs.h"
3053+#include "dentry.h"
3054+#include "dir.h"
8b6a4947 3055+#include "dirren.h"
7f207e10
AM
3056+#include "dynop.h"
3057+#include "file.h"
3058+#include "fstype.h"
8b6a4947 3059+#include "hbl.h"
7f207e10 3060+#include "inode.h"
acd2b654 3061+#include "lcnt.h"
7f207e10
AM
3062+#include "loop.h"
3063+#include "module.h"
7f207e10
AM
3064+#include "opts.h"
3065+#include "rwsem.h"
7f207e10
AM
3066+#include "super.h"
3067+#include "sysaufs.h"
3068+#include "vfsub.h"
3069+#include "whout.h"
3070+#include "wkq.h"
3071+
3072+#endif /* __KERNEL__ */
3073+#endif /* __AUFS_H__ */
3074diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
eca34b5c
AM
3075--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
3076+++ linux/fs/aufs/branch.c 2019-09-16 09:38:43.216175640 +0200
3077@@ -0,0 +1,1428 @@
cd7a4cd9 3078+// SPDX-License-Identifier: GPL-2.0
7f207e10 3079+/*
ba1aed25 3080+ * Copyright (C) 2005-2019 Junjiro R. Okajima
7f207e10
AM
3081+ *
3082+ * This program, aufs is free software; you can redistribute it and/or modify
3083+ * it under the terms of the GNU General Public License as published by
3084+ * the Free Software Foundation; either version 2 of the License, or
3085+ * (at your option) any later version.
3086+ *
3087+ * This program is distributed in the hope that it will be useful,
3088+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3089+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3090+ * GNU General Public License for more details.
3091+ *
3092+ * You should have received a copy of the GNU General Public License
523b37e3 3093+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
3094+ */
3095+
3096+/*
3097+ * branch management
3098+ */
3099+
027c5e7a 3100+#include <linux/compat.h>
7f207e10
AM
3101+#include <linux/statfs.h>
3102+#include "aufs.h"
3103+
3104+/*
3105+ * free a single branch
1facf9fc 3106+ */
3107+static void au_br_do_free(struct au_branch *br)
3108+{
3109+ int i;
3110+ struct au_wbr *wbr;
4a4d8108 3111+ struct au_dykey **key;
1facf9fc 3112+
027c5e7a 3113+ au_hnotify_fin_br(br);
8b6a4947
AM
3114+ /* always, regardless the mount option */
3115+ au_dr_hino_free(&br->br_dirren);
062440b3 3116+ au_xino_put(br);
1facf9fc 3117+
acd2b654
AM
3118+ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0));
3119+ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0);
3120+ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0));
3121+ au_lcnt_fin(&br->br_count, /*do_sync*/0);
1facf9fc 3122+
3123+ wbr = br->br_wbr;
3124+ if (wbr) {
3125+ for (i = 0; i < AuBrWh_Last; i++)
3126+ dput(wbr->wbr_wh[i]);
3127+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 3128+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 3129+ }
3130+
076b876e
AM
3131+ if (br->br_fhsm) {
3132+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 3133+ au_kfree_try_rcu(br->br_fhsm);
076b876e
AM
3134+ }
3135+
4a4d8108
AM
3136+ key = br->br_dykey;
3137+ for (i = 0; i < AuBrDynOp; i++, key++)
3138+ if (*key)
3139+ au_dy_put(*key);
3140+ else
3141+ break;
3142+
537831f9 3143+ /* recursive lock, s_umount of branch's */
acd2b654 3144+ /* synchronize_rcu(); */ /* why? */
537831f9 3145+ lockdep_off();
86dc4139 3146+ path_put(&br->br_path);
537831f9 3147+ lockdep_on();
9f237c51 3148+ au_kfree_rcu(wbr);
acd2b654
AM
3149+ au_lcnt_wait_for_fin(&br->br_nfiles);
3150+ au_lcnt_wait_for_fin(&br->br_count);
3151+ /* I don't know why, but percpu_refcount requires this */
3152+ /* synchronize_rcu(); */
9f237c51 3153+ au_kfree_rcu(br);
1facf9fc 3154+}
3155+
3156+/*
3157+ * frees all branches
3158+ */
3159+void au_br_free(struct au_sbinfo *sbinfo)
3160+{
3161+ aufs_bindex_t bmax;
3162+ struct au_branch **br;
3163+
dece6358
AM
3164+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3165+
5afbbe0d 3166+ bmax = sbinfo->si_bbot + 1;
1facf9fc 3167+ br = sbinfo->si_branch;
3168+ while (bmax--)
3169+ au_br_do_free(*br++);
3170+}
3171+
3172+/*
3173+ * find the index of a branch which is specified by @br_id.
3174+ */
3175+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
3176+{
5afbbe0d 3177+ aufs_bindex_t bindex, bbot;
1facf9fc 3178+
5afbbe0d
AM
3179+ bbot = au_sbbot(sb);
3180+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 3181+ if (au_sbr_id(sb, bindex) == br_id)
3182+ return bindex;
3183+ return -1;
3184+}
3185+
3186+/* ---------------------------------------------------------------------- */
3187+
3188+/*
3189+ * add a branch
3190+ */
3191+
b752ccd1
AM
3192+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
3193+ struct dentry *h_root)
1facf9fc 3194+{
b752ccd1
AM
3195+ if (unlikely(h_adding == h_root
3196+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 3197+ return 1;
b752ccd1
AM
3198+ if (h_adding->d_sb != h_root->d_sb)
3199+ return 0;
3200+ return au_test_subdir(h_adding, h_root)
3201+ || au_test_subdir(h_root, h_adding);
1facf9fc 3202+}
3203+
3204+/*
3205+ * returns a newly allocated branch. @new_nbranch is a number of branches
3206+ * after adding a branch.
3207+ */
3208+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
3209+ int perm)
3210+{
3211+ struct au_branch *add_branch;
3212+ struct dentry *root;
5527c038 3213+ struct inode *inode;
4a4d8108 3214+ int err;
1facf9fc 3215+
4a4d8108 3216+ err = -ENOMEM;
be52b249 3217+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS);
1facf9fc 3218+ if (unlikely(!add_branch))
3219+ goto out;
acd2b654 3220+ add_branch->br_xino = au_xino_alloc(/*nfile*/1);
062440b3 3221+ if (unlikely(!add_branch->br_xino))
521ced18 3222+ goto out_br;
027c5e7a
AM
3223+ err = au_hnotify_init_br(add_branch, perm);
3224+ if (unlikely(err))
062440b3 3225+ goto out_xino;
027c5e7a 3226+
1facf9fc 3227+ if (au_br_writable(perm)) {
3228+ /* may be freed separately at changing the branch permission */
be52b249 3229+ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr),
1facf9fc 3230+ GFP_NOFS);
3231+ if (unlikely(!add_branch->br_wbr))
027c5e7a 3232+ goto out_hnotify;
1facf9fc 3233+ }
3234+
076b876e
AM
3235+ if (au_br_fhsm(perm)) {
3236+ err = au_fhsm_br_alloc(add_branch);
3237+ if (unlikely(err))
3238+ goto out_wbr;
3239+ }
3240+
521ced18 3241+ root = sb->s_root;
e2f27e51 3242+ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0);
4a4d8108 3243+ if (!err)
e2f27e51 3244+ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0);
5527c038
JR
3245+ if (!err) {
3246+ inode = d_inode(root);
1c60b727
AM
3247+ err = au_hinode_realloc(au_ii(inode), new_nbranch,
3248+ /*may_shrink*/0);
5527c038 3249+ }
4a4d8108
AM
3250+ if (!err)
3251+ return add_branch; /* success */
1facf9fc 3252+
076b876e 3253+out_wbr:
9f237c51 3254+ au_kfree_rcu(add_branch->br_wbr);
027c5e7a
AM
3255+out_hnotify:
3256+ au_hnotify_fin_br(add_branch);
062440b3
AM
3257+out_xino:
3258+ au_xino_put(add_branch);
4f0767ce 3259+out_br:
9f237c51 3260+ au_kfree_rcu(add_branch);
4f0767ce 3261+out:
4a4d8108 3262+ return ERR_PTR(err);
1facf9fc 3263+}
3264+
3265+/*
3266+ * test if the branch permission is legal or not.
3267+ */
3268+static int test_br(struct inode *inode, int brperm, char *path)
3269+{
3270+ int err;
3271+
4a4d8108
AM
3272+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
3273+ if (!err)
3274+ goto out;
1facf9fc 3275+
4a4d8108
AM
3276+ err = -EINVAL;
3277+ pr_err("write permission for readonly mount or inode, %s\n", path);
3278+
4f0767ce 3279+out:
1facf9fc 3280+ return err;
3281+}
3282+
3283+/*
3284+ * returns:
3285+ * 0: success, the caller will add it
3286+ * plus: success, it is already unified, the caller should ignore it
3287+ * minus: error
3288+ */
3289+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
3290+{
3291+ int err;
5afbbe0d 3292+ aufs_bindex_t bbot, bindex;
5527c038 3293+ struct dentry *root, *h_dentry;
1facf9fc 3294+ struct inode *inode, *h_inode;
3295+
3296+ root = sb->s_root;
5afbbe0d
AM
3297+ bbot = au_sbbot(sb);
3298+ if (unlikely(bbot >= 0
1facf9fc 3299+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
3300+ err = 1;
3301+ if (!remount) {
3302+ err = -EINVAL;
4a4d8108 3303+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 3304+ }
3305+ goto out;
3306+ }
3307+
3308+ err = -ENOSPC; /* -E2BIG; */
3309+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
5afbbe0d 3310+ || AUFS_BRANCH_MAX - 1 <= bbot)) {
4a4d8108 3311+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 3312+ goto out;
3313+ }
3314+
3315+ err = -EDOM;
5afbbe0d 3316+ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) {
4a4d8108 3317+ pr_err("bad index %d\n", add->bindex);
1facf9fc 3318+ goto out;
3319+ }
3320+
5527c038 3321+ inode = d_inode(add->path.dentry);
1facf9fc 3322+ err = -ENOENT;
3323+ if (unlikely(!inode->i_nlink)) {
4a4d8108 3324+ pr_err("no existence %s\n", add->pathname);
1facf9fc 3325+ goto out;
3326+ }
3327+
3328+ err = -EINVAL;
3329+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 3330+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 3331+ goto out;
3332+ }
3333+
3334+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
3335+ pr_err("unsupported filesystem, %s (%s)\n",
3336+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 3337+ goto out;
3338+ }
3339+
c1595e42
JR
3340+ if (unlikely(inode->i_sb->s_stack_depth)) {
3341+ pr_err("already stacked, %s (%s)\n",
3342+ add->pathname, au_sbtype(inode->i_sb));
3343+ goto out;
3344+ }
3345+
5527c038 3346+ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname);
1facf9fc 3347+ if (unlikely(err))
3348+ goto out;
3349+
5afbbe0d 3350+ if (bbot < 0)
1facf9fc 3351+ return 0; /* success */
3352+
3353+ err = -EINVAL;
5afbbe0d 3354+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 3355+ if (unlikely(test_overlap(sb, add->path.dentry,
3356+ au_h_dptr(root, bindex)))) {
4a4d8108 3357+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 3358+ goto out;
3359+ }
3360+
3361+ err = 0;
3362+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
5527c038
JR
3363+ h_dentry = au_h_dptr(root, 0);
3364+ h_inode = d_inode(h_dentry);
1facf9fc 3365+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
0c3ec466
AM
3366+ || !uid_eq(h_inode->i_uid, inode->i_uid)
3367+ || !gid_eq(h_inode->i_gid, inode->i_gid))
3368+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
3369+ add->pathname,
3370+ i_uid_read(inode), i_gid_read(inode),
3371+ (inode->i_mode & S_IALLUGO),
3372+ i_uid_read(h_inode), i_gid_read(h_inode),
3373+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 3374+ }
3375+
4f0767ce 3376+out:
1facf9fc 3377+ return err;
3378+}
3379+
3380+/*
3381+ * initialize or clean the whiteouts for an adding branch
3382+ */
3383+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
86dc4139 3384+ int new_perm)
1facf9fc 3385+{
3386+ int err, old_perm;
3387+ aufs_bindex_t bindex;
febd17d6 3388+ struct inode *h_inode;
1facf9fc 3389+ struct au_wbr *wbr;
3390+ struct au_hinode *hdir;
5527c038 3391+ struct dentry *h_dentry;
1facf9fc 3392+
86dc4139
AM
3393+ err = vfsub_mnt_want_write(au_br_mnt(br));
3394+ if (unlikely(err))
3395+ goto out;
3396+
1facf9fc 3397+ wbr = br->br_wbr;
3398+ old_perm = br->br_perm;
3399+ br->br_perm = new_perm;
3400+ hdir = NULL;
febd17d6 3401+ h_inode = NULL;
1facf9fc 3402+ bindex = au_br_index(sb, br->br_id);
3403+ if (0 <= bindex) {
5527c038 3404+ hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 3405+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 3406+ } else {
5527c038 3407+ h_dentry = au_br_dentry(br);
febd17d6
JR
3408+ h_inode = d_inode(h_dentry);
3409+ inode_lock_nested(h_inode, AuLsc_I_PARENT);
1facf9fc 3410+ }
3411+ if (!wbr)
86dc4139 3412+ err = au_wh_init(br, sb);
1facf9fc 3413+ else {
3414+ wbr_wh_write_lock(wbr);
86dc4139 3415+ err = au_wh_init(br, sb);
1facf9fc 3416+ wbr_wh_write_unlock(wbr);
3417+ }
3418+ if (hdir)
5afbbe0d 3419+ au_hn_inode_unlock(hdir);
1facf9fc 3420+ else
febd17d6 3421+ inode_unlock(h_inode);
86dc4139 3422+ vfsub_mnt_drop_write(au_br_mnt(br));
1facf9fc 3423+ br->br_perm = old_perm;
3424+
3425+ if (!err && wbr && !au_br_writable(new_perm)) {
9f237c51 3426+ au_kfree_rcu(wbr);
1facf9fc 3427+ br->br_wbr = NULL;
3428+ }
3429+
86dc4139 3430+out:
1facf9fc 3431+ return err;
3432+}
3433+
3434+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
86dc4139 3435+ int perm)
1facf9fc 3436+{
3437+ int err;
4a4d8108 3438+ struct kstatfs kst;
1facf9fc 3439+ struct au_wbr *wbr;
3440+
3441+ wbr = br->br_wbr;
dece6358 3442+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 3443+ atomic_set(&wbr->wbr_wh_running, 0);
1facf9fc 3444+
4a4d8108
AM
3445+ /*
3446+ * a limit for rmdir/rename a dir
523b37e3 3447+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h
4a4d8108 3448+ */
86dc4139 3449+ err = vfs_statfs(&br->br_path, &kst);
4a4d8108
AM
3450+ if (unlikely(err))
3451+ goto out;
3452+ err = -EINVAL;
3453+ if (kst.f_namelen >= NAME_MAX)
86dc4139 3454+ err = au_br_init_wh(sb, br, perm);
4a4d8108 3455+ else
523b37e3
AM
3456+ pr_err("%pd(%s), unsupported namelen %ld\n",
3457+ au_br_dentry(br),
86dc4139 3458+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen);
1facf9fc 3459+
4f0767ce 3460+out:
1facf9fc 3461+ return err;
3462+}
3463+
c1595e42 3464+/* initialize a new branch */
1facf9fc 3465+static int au_br_init(struct au_branch *br, struct super_block *sb,
3466+ struct au_opt_add *add)
3467+{
3468+ int err;
062440b3
AM
3469+ struct au_branch *brbase;
3470+ struct file *xf;
5527c038 3471+ struct inode *h_inode;
1facf9fc 3472+
3473+ err = 0;
1facf9fc 3474+ br->br_perm = add->perm;
86dc4139 3475+ br->br_path = add->path; /* set first, path_get() later */
4a4d8108 3476+ spin_lock_init(&br->br_dykey_lock);
acd2b654
AM
3477+ au_lcnt_init(&br->br_nfiles, /*release*/NULL);
3478+ au_lcnt_init(&br->br_count, /*release*/NULL);
1facf9fc 3479+ br->br_id = au_new_br_id(sb);
7f207e10 3480+ AuDebugOn(br->br_id < 0);
1facf9fc 3481+
8b6a4947
AM
3482+ /* always, regardless the given option */
3483+ err = au_dr_br_init(sb, br, &add->path);
3484+ if (unlikely(err))
3485+ goto out_err;
3486+
1facf9fc 3487+ if (au_br_writable(add->perm)) {
86dc4139 3488+ err = au_wbr_init(br, sb, add->perm);
1facf9fc 3489+ if (unlikely(err))
b752ccd1 3490+ goto out_err;
1facf9fc 3491+ }
3492+
3493+ if (au_opt_test(au_mntflags(sb), XINO)) {
062440b3 3494+ brbase = au_sbr(sb, 0);
acd2b654 3495+ xf = au_xino_file(brbase->br_xino, /*idx*/-1);
062440b3 3496+ AuDebugOn(!xf);
5527c038 3497+ h_inode = d_inode(add->path.dentry);
062440b3 3498+ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path);
1facf9fc 3499+ if (unlikely(err)) {
acd2b654 3500+ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1));
b752ccd1 3501+ goto out_err;
1facf9fc 3502+ }
3503+ }
3504+
3505+ sysaufs_br_init(br);
86dc4139 3506+ path_get(&br->br_path);
b752ccd1 3507+ goto out; /* success */
1facf9fc 3508+
4f0767ce 3509+out_err:
86dc4139 3510+ memset(&br->br_path, 0, sizeof(br->br_path));
4f0767ce 3511+out:
1facf9fc 3512+ return err;
3513+}
3514+
3515+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
5afbbe0d 3516+ struct au_branch *br, aufs_bindex_t bbot,
1facf9fc 3517+ aufs_bindex_t amount)
3518+{
3519+ struct au_branch **brp;
3520+
dece6358
AM
3521+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3522+
1facf9fc 3523+ brp = sbinfo->si_branch + bindex;
3524+ memmove(brp + 1, brp, sizeof(*brp) * amount);
3525+ *brp = br;
5afbbe0d
AM
3526+ sbinfo->si_bbot++;
3527+ if (unlikely(bbot < 0))
3528+ sbinfo->si_bbot = 0;
1facf9fc 3529+}
3530+
3531+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
5afbbe0d 3532+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 3533+{
3534+ struct au_hdentry *hdp;
3535+
1308ab2a 3536+ AuRwMustWriteLock(&dinfo->di_rwsem);
3537+
5afbbe0d 3538+ hdp = au_hdentry(dinfo, bindex);
1facf9fc 3539+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
3540+ au_h_dentry_init(hdp);
5afbbe0d
AM
3541+ dinfo->di_bbot++;
3542+ if (unlikely(bbot < 0))
3543+ dinfo->di_btop = 0;
1facf9fc 3544+}
3545+
3546+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
5afbbe0d 3547+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 3548+{
3549+ struct au_hinode *hip;
3550+
1308ab2a 3551+ AuRwMustWriteLock(&iinfo->ii_rwsem);
3552+
5afbbe0d 3553+ hip = au_hinode(iinfo, bindex);
1facf9fc 3554+ memmove(hip + 1, hip, sizeof(*hip) * amount);
5afbbe0d
AM
3555+ au_hinode_init(hip);
3556+ iinfo->ii_bbot++;
3557+ if (unlikely(bbot < 0))
3558+ iinfo->ii_btop = 0;
1facf9fc 3559+}
3560+
86dc4139
AM
3561+static void au_br_do_add(struct super_block *sb, struct au_branch *br,
3562+ aufs_bindex_t bindex)
1facf9fc 3563+{
86dc4139 3564+ struct dentry *root, *h_dentry;
5527c038 3565+ struct inode *root_inode, *h_inode;
5afbbe0d 3566+ aufs_bindex_t bbot, amount;
1facf9fc 3567+
3568+ root = sb->s_root;
5527c038 3569+ root_inode = d_inode(root);
5afbbe0d
AM
3570+ bbot = au_sbbot(sb);
3571+ amount = bbot + 1 - bindex;
86dc4139 3572+ h_dentry = au_br_dentry(br);
53392da6 3573+ au_sbilist_lock();
5afbbe0d
AM
3574+ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount);
3575+ au_br_do_add_hdp(au_di(root), bindex, bbot, amount);
3576+ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount);
1facf9fc 3577+ au_set_h_dptr(root, bindex, dget(h_dentry));
5527c038
JR
3578+ h_inode = d_inode(h_dentry);
3579+ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0);
53392da6 3580+ au_sbilist_unlock();
1facf9fc 3581+}
3582+
3583+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
3584+{
3585+ int err;
5afbbe0d 3586+ aufs_bindex_t bbot, add_bindex;
1facf9fc 3587+ struct dentry *root, *h_dentry;
3588+ struct inode *root_inode;
3589+ struct au_branch *add_branch;
3590+
3591+ root = sb->s_root;
5527c038 3592+ root_inode = d_inode(root);
1facf9fc 3593+ IMustLock(root_inode);
5afbbe0d 3594+ IiMustWriteLock(root_inode);
1facf9fc 3595+ err = test_add(sb, add, remount);
3596+ if (unlikely(err < 0))
3597+ goto out;
3598+ if (err) {
3599+ err = 0;
3600+ goto out; /* success */
3601+ }
3602+
5afbbe0d
AM
3603+ bbot = au_sbbot(sb);
3604+ add_branch = au_br_alloc(sb, bbot + 2, add->perm);
1facf9fc 3605+ err = PTR_ERR(add_branch);
3606+ if (IS_ERR(add_branch))
3607+ goto out;
3608+
3609+ err = au_br_init(add_branch, sb, add);
3610+ if (unlikely(err)) {
3611+ au_br_do_free(add_branch);
3612+ goto out;
3613+ }
3614+
3615+ add_bindex = add->bindex;
062440b3
AM
3616+ sysaufs_brs_del(sb, add_bindex); /* remove successors */
3617+ au_br_do_add(sb, add_branch, add_bindex);
3618+ sysaufs_brs_add(sb, add_bindex); /* append successors */
3619+ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */
1facf9fc 3620+
86dc4139 3621+ h_dentry = add->path.dentry;
1308ab2a 3622+ if (!add_bindex) {
1facf9fc 3623+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 3624+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
3625+ } else
5527c038 3626+ au_add_nlink(root_inode, d_inode(h_dentry));
1facf9fc 3627+
4f0767ce 3628+out:
1facf9fc 3629+ return err;
3630+}
3631+
3632+/* ---------------------------------------------------------------------- */
3633+
79b8bda9 3634+static unsigned long long au_farray_cb(struct super_block *sb, void *a,
076b876e
AM
3635+ unsigned long long max __maybe_unused,
3636+ void *arg)
3637+{
3638+ unsigned long long n;
3639+ struct file **p, *f;
8b6a4947
AM
3640+ struct hlist_bl_head *files;
3641+ struct hlist_bl_node *pos;
076b876e 3642+ struct au_finfo *finfo;
076b876e
AM
3643+
3644+ n = 0;
3645+ p = a;
3646+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
3647+ hlist_bl_lock(files);
3648+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
076b876e
AM
3649+ f = finfo->fi_file;
3650+ if (file_count(f)
3651+ && !special_file(file_inode(f)->i_mode)) {
3652+ get_file(f);
3653+ *p++ = f;
3654+ n++;
3655+ AuDebugOn(n > max);
3656+ }
3657+ }
8b6a4947 3658+ hlist_bl_unlock(files);
076b876e
AM
3659+
3660+ return n;
3661+}
3662+
3663+static struct file **au_farray_alloc(struct super_block *sb,
3664+ unsigned long long *max)
3665+{
acd2b654
AM
3666+ struct au_sbinfo *sbi;
3667+
3668+ sbi = au_sbi(sb);
3669+ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1);
79b8bda9 3670+ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL);
076b876e
AM
3671+}
3672+
3673+static void au_farray_free(struct file **a, unsigned long long max)
3674+{
3675+ unsigned long long ull;
3676+
3677+ for (ull = 0; ull < max; ull++)
3678+ if (a[ull])
3679+ fput(a[ull]);
be52b249 3680+ kvfree(a);
076b876e
AM
3681+}
3682+
3683+/* ---------------------------------------------------------------------- */
3684+
1facf9fc 3685+/*
3686+ * delete a branch
3687+ */
3688+
3689+/* to show the line number, do not make it inlined function */
4a4d8108 3690+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 3691+ if (do_info) \
4a4d8108 3692+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 3693+} while (0)
3694+
5afbbe0d
AM
3695+static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop,
3696+ aufs_bindex_t bbot)
027c5e7a 3697+{
5afbbe0d 3698+ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot;
027c5e7a
AM
3699+}
3700+
5afbbe0d
AM
3701+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop,
3702+ aufs_bindex_t bbot)
027c5e7a 3703+{
5afbbe0d 3704+ return au_test_ibusy(d_inode(dentry), btop, bbot);
027c5e7a
AM
3705+}
3706+
1facf9fc 3707+/*
3708+ * test if the branch is deletable or not.
3709+ */
3710+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 3711+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3712+{
3713+ int err, i, j, ndentry;
5afbbe0d 3714+ aufs_bindex_t btop, bbot;
1facf9fc 3715+ struct au_dcsub_pages dpages;
3716+ struct au_dpage *dpage;
3717+ struct dentry *d;
1facf9fc 3718+
3719+ err = au_dpages_init(&dpages, GFP_NOFS);
3720+ if (unlikely(err))
3721+ goto out;
3722+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
3723+ if (unlikely(err))
3724+ goto out_dpages;
3725+
1facf9fc 3726+ for (i = 0; !err && i < dpages.ndpage; i++) {
3727+ dpage = dpages.dpages + i;
3728+ ndentry = dpage->ndentry;
3729+ for (j = 0; !err && j < ndentry; j++) {
3730+ d = dpage->dentries[j];
c1595e42 3731+ AuDebugOn(au_dcount(d) <= 0);
027c5e7a 3732+ if (!au_digen_test(d, sigen)) {
1facf9fc 3733+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
3734+ if (unlikely(au_dbrange_test(d))) {
3735+ di_read_unlock(d, AuLock_IR);
3736+ continue;
3737+ }
3738+ } else {
1facf9fc 3739+ di_write_lock_child(d);
027c5e7a
AM
3740+ if (unlikely(au_dbrange_test(d))) {
3741+ di_write_unlock(d);
3742+ continue;
3743+ }
1facf9fc 3744+ err = au_reval_dpath(d, sigen);
3745+ if (!err)
3746+ di_downgrade_lock(d, AuLock_IR);
3747+ else {
3748+ di_write_unlock(d);
3749+ break;
3750+ }
3751+ }
3752+
027c5e7a 3753+ /* AuDbgDentry(d); */
5afbbe0d
AM
3754+ btop = au_dbtop(d);
3755+ bbot = au_dbbot(d);
3756+ if (btop <= bindex
3757+ && bindex <= bbot
1facf9fc 3758+ && au_h_dptr(d, bindex)
5afbbe0d 3759+ && au_test_dbusy(d, btop, bbot)) {
1facf9fc 3760+ err = -EBUSY;
523b37e3 3761+ AuVerbose(verbose, "busy %pd\n", d);
027c5e7a 3762+ AuDbgDentry(d);
1facf9fc 3763+ }
3764+ di_read_unlock(d, AuLock_IR);
3765+ }
3766+ }
3767+
4f0767ce 3768+out_dpages:
1facf9fc 3769+ au_dpages_free(&dpages);
4f0767ce 3770+out:
1facf9fc 3771+ return err;
3772+}
3773+
3774+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 3775+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3776+{
3777+ int err;
7f207e10
AM
3778+ unsigned long long max, ull;
3779+ struct inode *i, **array;
5afbbe0d 3780+ aufs_bindex_t btop, bbot;
1facf9fc 3781+
7f207e10
AM
3782+ array = au_iarray_alloc(sb, &max);
3783+ err = PTR_ERR(array);
3784+ if (IS_ERR(array))
3785+ goto out;
3786+
1facf9fc 3787+ err = 0;
7f207e10
AM
3788+ AuDbg("b%d\n", bindex);
3789+ for (ull = 0; !err && ull < max; ull++) {
3790+ i = array[ull];
076b876e
AM
3791+ if (unlikely(!i))
3792+ break;
7f207e10 3793+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 3794+ continue;
3795+
7f207e10 3796+ /* AuDbgInode(i); */
537831f9 3797+ if (au_iigen(i, NULL) == sigen)
1facf9fc 3798+ ii_read_lock_child(i);
3799+ else {
3800+ ii_write_lock_child(i);
027c5e7a
AM
3801+ err = au_refresh_hinode_self(i);
3802+ au_iigen_dec(i);
1facf9fc 3803+ if (!err)
3804+ ii_downgrade_lock(i);
3805+ else {
3806+ ii_write_unlock(i);
3807+ break;
3808+ }
3809+ }
3810+
5afbbe0d
AM
3811+ btop = au_ibtop(i);
3812+ bbot = au_ibbot(i);
3813+ if (btop <= bindex
3814+ && bindex <= bbot
1facf9fc 3815+ && au_h_iptr(i, bindex)
5afbbe0d 3816+ && au_test_ibusy(i, btop, bbot)) {
1facf9fc 3817+ err = -EBUSY;
3818+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 3819+ AuDbgInode(i);
1facf9fc 3820+ }
3821+ ii_read_unlock(i);
3822+ }
7f207e10 3823+ au_iarray_free(array, max);
1facf9fc 3824+
7f207e10 3825+out:
1facf9fc 3826+ return err;
3827+}
3828+
b752ccd1
AM
3829+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
3830+ const unsigned int verbose)
1facf9fc 3831+{
3832+ int err;
3833+ unsigned int sigen;
3834+
3835+ sigen = au_sigen(root->d_sb);
3836+ DiMustNoWaiters(root);
5527c038 3837+ IiMustNoWaiters(d_inode(root));
1facf9fc 3838+ di_write_unlock(root);
b752ccd1 3839+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 3840+ if (!err)
b752ccd1 3841+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 3842+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
3843+
3844+ return err;
3845+}
3846+
076b876e
AM
3847+static int test_dir_busy(struct file *file, aufs_bindex_t br_id,
3848+ struct file **to_free, int *idx)
3849+{
3850+ int err;
c1595e42 3851+ unsigned char matched, root;
5afbbe0d 3852+ aufs_bindex_t bindex, bbot;
076b876e
AM
3853+ struct au_fidir *fidir;
3854+ struct au_hfile *hfile;
3855+
3856+ err = 0;
2000de60 3857+ root = IS_ROOT(file->f_path.dentry);
c1595e42
JR
3858+ if (root) {
3859+ get_file(file);
3860+ to_free[*idx] = file;
3861+ (*idx)++;
3862+ goto out;
3863+ }
3864+
076b876e 3865+ matched = 0;
076b876e
AM
3866+ fidir = au_fi(file)->fi_hdir;
3867+ AuDebugOn(!fidir);
5afbbe0d
AM
3868+ bbot = au_fbbot_dir(file);
3869+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) {
076b876e
AM
3870+ hfile = fidir->fd_hfile + bindex;
3871+ if (!hfile->hf_file)
3872+ continue;
3873+
c1595e42 3874+ if (hfile->hf_br->br_id == br_id) {
076b876e 3875+ matched = 1;
076b876e 3876+ break;
c1595e42 3877+ }
076b876e 3878+ }
c1595e42 3879+ if (matched)
076b876e
AM
3880+ err = -EBUSY;
3881+
3882+out:
3883+ return err;
3884+}
3885+
3886+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id,
3887+ struct file **to_free, int opened)
3888+{
3889+ int err, idx;
3890+ unsigned long long ull, max;
5afbbe0d 3891+ aufs_bindex_t btop;
076b876e 3892+ struct file *file, **array;
076b876e
AM
3893+ struct dentry *root;
3894+ struct au_hfile *hfile;
3895+
3896+ array = au_farray_alloc(sb, &max);
3897+ err = PTR_ERR(array);
3898+ if (IS_ERR(array))
3899+ goto out;
3900+
3901+ err = 0;
3902+ idx = 0;
3903+ root = sb->s_root;
3904+ di_write_unlock(root);
3905+ for (ull = 0; ull < max; ull++) {
3906+ file = array[ull];
3907+ if (unlikely(!file))
3908+ break;
3909+
3910+ /* AuDbg("%pD\n", file); */
3911+ fi_read_lock(file);
5afbbe0d 3912+ btop = au_fbtop(file);
2000de60 3913+ if (!d_is_dir(file->f_path.dentry)) {
076b876e
AM
3914+ hfile = &au_fi(file)->fi_htop;
3915+ if (hfile->hf_br->br_id == br_id)
3916+ err = -EBUSY;
3917+ } else
3918+ err = test_dir_busy(file, br_id, to_free, &idx);
3919+ fi_read_unlock(file);
3920+ if (unlikely(err))
3921+ break;
3922+ }
3923+ di_write_lock_child(root);
3924+ au_farray_free(array, max);
3925+ AuDebugOn(idx > opened);
3926+
3927+out:
3928+ return err;
3929+}
3930+
3931+static void br_del_file(struct file **to_free, unsigned long long opened,
062440b3 3932+ aufs_bindex_t br_id)
076b876e
AM
3933+{
3934+ unsigned long long ull;
5afbbe0d 3935+ aufs_bindex_t bindex, btop, bbot, bfound;
076b876e
AM
3936+ struct file *file;
3937+ struct au_fidir *fidir;
3938+ struct au_hfile *hfile;
3939+
3940+ for (ull = 0; ull < opened; ull++) {
3941+ file = to_free[ull];
3942+ if (unlikely(!file))
3943+ break;
3944+
3945+ /* AuDbg("%pD\n", file); */
2000de60 3946+ AuDebugOn(!d_is_dir(file->f_path.dentry));
076b876e
AM
3947+ bfound = -1;
3948+ fidir = au_fi(file)->fi_hdir;
3949+ AuDebugOn(!fidir);
3950+ fi_write_lock(file);
5afbbe0d
AM
3951+ btop = au_fbtop(file);
3952+ bbot = au_fbbot_dir(file);
3953+ for (bindex = btop; bindex <= bbot; bindex++) {
076b876e
AM
3954+ hfile = fidir->fd_hfile + bindex;
3955+ if (!hfile->hf_file)
3956+ continue;
3957+
3958+ if (hfile->hf_br->br_id == br_id) {
3959+ bfound = bindex;
3960+ break;
3961+ }
3962+ }
3963+ AuDebugOn(bfound < 0);
3964+ au_set_h_fptr(file, bfound, NULL);
5afbbe0d
AM
3965+ if (bfound == btop) {
3966+ for (btop++; btop <= bbot; btop++)
3967+ if (au_hf_dir(file, btop)) {
3968+ au_set_fbtop(file, btop);
076b876e
AM
3969+ break;
3970+ }
3971+ }
3972+ fi_write_unlock(file);
3973+ }
3974+}
3975+
1facf9fc 3976+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
3977+ const aufs_bindex_t bindex,
5afbbe0d 3978+ const aufs_bindex_t bbot)
1facf9fc 3979+{
3980+ struct au_branch **brp, **p;
3981+
dece6358
AM
3982+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3983+
1facf9fc 3984+ brp = sbinfo->si_branch + bindex;
5afbbe0d
AM
3985+ if (bindex < bbot)
3986+ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex));
3987+ sbinfo->si_branch[0 + bbot] = NULL;
3988+ sbinfo->si_bbot--;
1facf9fc 3989+
e2f27e51
AM
3990+ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST,
3991+ /*may_shrink*/1);
1facf9fc 3992+ if (p)
3993+ sbinfo->si_branch = p;
4a4d8108 3994+ /* harmless error */
1facf9fc 3995+}
3996+
3997+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
5afbbe0d 3998+ const aufs_bindex_t bbot)
1facf9fc 3999+{
4000+ struct au_hdentry *hdp, *p;
4001+
1308ab2a 4002+ AuRwMustWriteLock(&dinfo->di_rwsem);
4003+
5afbbe0d
AM
4004+ hdp = au_hdentry(dinfo, bindex);
4005+ if (bindex < bbot)
4006+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex));
4007+ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */
4008+ dinfo->di_bbot--;
1facf9fc 4009+
e2f27e51
AM
4010+ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST,
4011+ /*may_shrink*/1);
1facf9fc 4012+ if (p)
4013+ dinfo->di_hdentry = p;
4a4d8108 4014+ /* harmless error */
1facf9fc 4015+}
4016+
4017+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
5afbbe0d 4018+ const aufs_bindex_t bbot)
1facf9fc 4019+{
4020+ struct au_hinode *hip, *p;
4021+
1308ab2a 4022+ AuRwMustWriteLock(&iinfo->ii_rwsem);
4023+
5afbbe0d
AM
4024+ hip = au_hinode(iinfo, bindex);
4025+ if (bindex < bbot)
4026+ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex));
4027+ /* au_hinode_init(au_hinode(iinfo, bbot)); */
4028+ iinfo->ii_bbot--;
1facf9fc 4029+
e2f27e51
AM
4030+ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST,
4031+ /*may_shrink*/1);
1facf9fc 4032+ if (p)
4033+ iinfo->ii_hinode = p;
4a4d8108 4034+ /* harmless error */
1facf9fc 4035+}
4036+
4037+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
4038+ struct au_branch *br)
4039+{
5afbbe0d 4040+ aufs_bindex_t bbot;
1facf9fc 4041+ struct au_sbinfo *sbinfo;
53392da6
AM
4042+ struct dentry *root, *h_root;
4043+ struct inode *inode, *h_inode;
4044+ struct au_hinode *hinode;
1facf9fc 4045+
dece6358
AM
4046+ SiMustWriteLock(sb);
4047+
1facf9fc 4048+ root = sb->s_root;
5527c038 4049+ inode = d_inode(root);
1facf9fc 4050+ sbinfo = au_sbi(sb);
5afbbe0d 4051+ bbot = sbinfo->si_bbot;
1facf9fc 4052+
53392da6
AM
4053+ h_root = au_h_dptr(root, bindex);
4054+ hinode = au_hi(inode, bindex);
4055+ h_inode = au_igrab(hinode->hi_inode);
4056+ au_hiput(hinode);
1facf9fc 4057+
53392da6 4058+ au_sbilist_lock();
5afbbe0d
AM
4059+ au_br_do_del_brp(sbinfo, bindex, bbot);
4060+ au_br_do_del_hdp(au_di(root), bindex, bbot);
4061+ au_br_do_del_hip(au_ii(inode), bindex, bbot);
53392da6
AM
4062+ au_sbilist_unlock();
4063+
8b6a4947
AM
4064+ /* ignore an error */
4065+ au_dr_br_fin(sb, br); /* always, regardless the mount option */
4066+
53392da6
AM
4067+ dput(h_root);
4068+ iput(h_inode);
4069+ au_br_do_free(br);
1facf9fc 4070+}
4071+
79b8bda9
AM
4072+static unsigned long long empty_cb(struct super_block *sb, void *array,
4073+ unsigned long long max, void *arg)
076b876e
AM
4074+{
4075+ return max;
4076+}
4077+
1facf9fc 4078+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
4079+{
4080+ int err, rerr, i;
076b876e 4081+ unsigned long long opened;
1facf9fc 4082+ unsigned int mnt_flags;
5afbbe0d 4083+ aufs_bindex_t bindex, bbot, br_id;
1facf9fc 4084+ unsigned char do_wh, verbose;
4085+ struct au_branch *br;
4086+ struct au_wbr *wbr;
076b876e
AM
4087+ struct dentry *root;
4088+ struct file **to_free;
1facf9fc 4089+
4090+ err = 0;
076b876e
AM
4091+ opened = 0;
4092+ to_free = NULL;
4093+ root = sb->s_root;
4094+ bindex = au_find_dbindex(root, del->h_path.dentry);
1facf9fc 4095+ if (bindex < 0) {
4096+ if (remount)
4097+ goto out; /* success */
4098+ err = -ENOENT;
4a4d8108 4099+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 4100+ goto out;
4101+ }
4102+ AuDbg("bindex b%d\n", bindex);
4103+
4104+ err = -EBUSY;
4105+ mnt_flags = au_mntflags(sb);
4106+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
5afbbe0d
AM
4107+ bbot = au_sbbot(sb);
4108+ if (unlikely(!bbot)) {
1facf9fc 4109+ AuVerbose(verbose, "no more branches left\n");
4110+ goto out;
4111+ }
acd2b654 4112+
1facf9fc 4113+ br = au_sbr(sb, bindex);
86dc4139 4114+ AuDebugOn(!path_equal(&br->br_path, &del->h_path));
acd2b654
AM
4115+ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) {
4116+ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry);
4117+ goto out;
4118+ }
076b876e
AM
4119+
4120+ br_id = br->br_id;
acd2b654 4121+ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1);
076b876e 4122+ if (unlikely(opened)) {
79b8bda9 4123+ to_free = au_array_alloc(&opened, empty_cb, sb, NULL);
076b876e
AM
4124+ err = PTR_ERR(to_free);
4125+ if (IS_ERR(to_free))
4126+ goto out;
4127+
4128+ err = test_file_busy(sb, br_id, to_free, opened);
4129+ if (unlikely(err)) {
4130+ AuVerbose(verbose, "%llu file(s) opened\n", opened);
4131+ goto out;
4132+ }
1facf9fc 4133+ }
4134+
4135+ wbr = br->br_wbr;
4136+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
4137+ if (do_wh) {
1308ab2a 4138+ /* instead of WbrWhMustWriteLock(wbr) */
4139+ SiMustWriteLock(sb);
1facf9fc 4140+ for (i = 0; i < AuBrWh_Last; i++) {
4141+ dput(wbr->wbr_wh[i]);
4142+ wbr->wbr_wh[i] = NULL;
4143+ }
4144+ }
4145+
076b876e 4146+ err = test_children_busy(root, bindex, verbose);
1facf9fc 4147+ if (unlikely(err)) {
4148+ if (do_wh)
4149+ goto out_wh;
4150+ goto out;
4151+ }
4152+
4153+ err = 0;
076b876e
AM
4154+ if (to_free) {
4155+ /*
4156+ * now we confirmed the branch is deletable.
4157+ * let's free the remaining opened dirs on the branch.
4158+ */
4159+ di_write_unlock(root);
4160+ br_del_file(to_free, opened, br_id);
4161+ di_write_lock_child(root);
4162+ }
4163+
062440b3
AM
4164+ sysaufs_brs_del(sb, bindex); /* remove successors */
4165+ dbgaufs_xino_del(br); /* remove one */
4166+ au_br_do_del(sb, bindex, br);
4167+ sysaufs_brs_add(sb, bindex); /* append successors */
4168+ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */
1facf9fc 4169+
1308ab2a 4170+ if (!bindex) {
5527c038 4171+ au_cpup_attr_all(d_inode(root), /*force*/1);
1308ab2a 4172+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
4173+ } else
5527c038 4174+ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry));
1facf9fc 4175+ if (au_opt_test(mnt_flags, PLINK))
4176+ au_plink_half_refresh(sb, br_id);
4177+
1facf9fc 4178+ goto out; /* success */
4179+
4f0767ce 4180+out_wh:
1facf9fc 4181+ /* revert */
86dc4139 4182+ rerr = au_br_init_wh(sb, br, br->br_perm);
1facf9fc 4183+ if (rerr)
0c3ec466
AM
4184+ pr_warn("failed re-creating base whiteout, %s. (%d)\n",
4185+ del->pathname, rerr);
4f0767ce 4186+out:
076b876e
AM
4187+ if (to_free)
4188+ au_farray_free(to_free, opened);
1facf9fc 4189+ return err;
4190+}
4191+
4192+/* ---------------------------------------------------------------------- */
4193+
027c5e7a
AM
4194+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
4195+{
4196+ int err;
5afbbe0d 4197+ aufs_bindex_t btop, bbot;
027c5e7a
AM
4198+ struct aufs_ibusy ibusy;
4199+ struct inode *inode, *h_inode;
4200+
4201+ err = -EPERM;
4202+ if (unlikely(!capable(CAP_SYS_ADMIN)))
4203+ goto out;
4204+
4205+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
4206+ if (!err)
ba1aed25
AM
4207+ /* VERIFY_WRITE */
4208+ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino));
027c5e7a
AM
4209+ if (unlikely(err)) {
4210+ err = -EFAULT;
4211+ AuTraceErr(err);
4212+ goto out;
4213+ }
4214+
4215+ err = -EINVAL;
4216+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d 4217+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb)))
027c5e7a
AM
4218+ goto out_unlock;
4219+
4220+ err = 0;
4221+ ibusy.h_ino = 0; /* invalid */
4222+ inode = ilookup(sb, ibusy.ino);
4223+ if (!inode
4224+ || inode->i_ino == AUFS_ROOT_INO
5afbbe0d 4225+ || au_is_bad_inode(inode))
027c5e7a
AM
4226+ goto out_unlock;
4227+
4228+ ii_read_lock_child(inode);
5afbbe0d
AM
4229+ btop = au_ibtop(inode);
4230+ bbot = au_ibbot(inode);
4231+ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) {
027c5e7a 4232+ h_inode = au_h_iptr(inode, ibusy.bindex);
5afbbe0d 4233+ if (h_inode && au_test_ibusy(inode, btop, bbot))
027c5e7a
AM
4234+ ibusy.h_ino = h_inode->i_ino;
4235+ }
4236+ ii_read_unlock(inode);
4237+ iput(inode);
4238+
4239+out_unlock:
4240+ si_read_unlock(sb);
4241+ if (!err) {
4242+ err = __put_user(ibusy.h_ino, &arg->h_ino);
4243+ if (unlikely(err)) {
4244+ err = -EFAULT;
4245+ AuTraceErr(err);
4246+ }
4247+ }
4248+out:
4249+ return err;
4250+}
4251+
4252+long au_ibusy_ioctl(struct file *file, unsigned long arg)
4253+{
2000de60 4254+ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg);
027c5e7a
AM
4255+}
4256+
4257+#ifdef CONFIG_COMPAT
4258+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
4259+{
2000de60 4260+ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg));
027c5e7a
AM
4261+}
4262+#endif
4263+
4264+/* ---------------------------------------------------------------------- */
4265+
1facf9fc 4266+/*
4267+ * change a branch permission
4268+ */
4269+
dece6358
AM
4270+static void au_warn_ima(void)
4271+{
4272+#ifdef CONFIG_IMA
1308ab2a 4273+ /* since it doesn't support mark_files_ro() */
027c5e7a 4274+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
4275+#endif
4276+}
4277+
1facf9fc 4278+static int do_need_sigen_inc(int a, int b)
4279+{
4280+ return au_br_whable(a) && !au_br_whable(b);
4281+}
4282+
4283+static int need_sigen_inc(int old, int new)
4284+{
4285+ return do_need_sigen_inc(old, new)
4286+ || do_need_sigen_inc(new, old);
4287+}
4288+
4289+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
4290+{
7f207e10 4291+ int err, do_warn;
027c5e7a 4292+ unsigned int mnt_flags;
7f207e10 4293+ unsigned long long ull, max;
e49829fe 4294+ aufs_bindex_t br_id;
38d290e6 4295+ unsigned char verbose, writer;
7f207e10 4296+ struct file *file, *hf, **array;
e49829fe 4297+ struct au_hfile *hfile;
eca34b5c 4298+ struct inode *h_inode;
1facf9fc 4299+
027c5e7a
AM
4300+ mnt_flags = au_mntflags(sb);
4301+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
4302+
7f207e10
AM
4303+ array = au_farray_alloc(sb, &max);
4304+ err = PTR_ERR(array);
4305+ if (IS_ERR(array))
1facf9fc 4306+ goto out;
4307+
7f207e10 4308+ do_warn = 0;
e49829fe 4309+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
4310+ for (ull = 0; ull < max; ull++) {
4311+ file = array[ull];
076b876e
AM
4312+ if (unlikely(!file))
4313+ break;
1facf9fc 4314+
523b37e3 4315+ /* AuDbg("%pD\n", file); */
1facf9fc 4316+ fi_read_lock(file);
4317+ if (unlikely(au_test_mmapped(file))) {
4318+ err = -EBUSY;
523b37e3 4319+ AuVerbose(verbose, "mmapped %pD\n", file);
7f207e10 4320+ AuDbgFile(file);
1facf9fc 4321+ FiMustNoWaiters(file);
4322+ fi_read_unlock(file);
7f207e10 4323+ goto out_array;
1facf9fc 4324+ }
4325+
e49829fe
JR
4326+ hfile = &au_fi(file)->fi_htop;
4327+ hf = hfile->hf_file;
7e9cd9fe 4328+ if (!d_is_reg(file->f_path.dentry)
1facf9fc 4329+ || !(file->f_mode & FMODE_WRITE)
e49829fe 4330+ || hfile->hf_br->br_id != br_id
7f207e10
AM
4331+ || !(hf->f_mode & FMODE_WRITE))
4332+ array[ull] = NULL;
4333+ else {
4334+ do_warn = 1;
4335+ get_file(file);
1facf9fc 4336+ }
4337+
1facf9fc 4338+ FiMustNoWaiters(file);
4339+ fi_read_unlock(file);
7f207e10
AM
4340+ fput(file);
4341+ }
1facf9fc 4342+
4343+ err = 0;
7f207e10 4344+ if (do_warn)
dece6358 4345+ au_warn_ima();
7f207e10
AM
4346+
4347+ for (ull = 0; ull < max; ull++) {
4348+ file = array[ull];
4349+ if (!file)
4350+ continue;
4351+
1facf9fc 4352+ /* todo: already flushed? */
523b37e3
AM
4353+ /*
4354+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its
4355+ * approach which resets f_mode and calls mnt_drop_write() and
4356+ * file_release_write() for each file, because the branch
4357+ * attribute in aufs world is totally different from the native
4358+ * fs rw/ro mode.
4359+ */
7f207e10
AM
4360+ /* fi_read_lock(file); */
4361+ hfile = &au_fi(file)->fi_htop;
4362+ hf = hfile->hf_file;
4363+ /* fi_read_unlock(file); */
027c5e7a 4364+ spin_lock(&hf->f_lock);
38d290e6
JR
4365+ writer = !!(hf->f_mode & FMODE_WRITER);
4366+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER);
027c5e7a 4367+ spin_unlock(&hf->f_lock);
38d290e6 4368+ if (writer) {
eca34b5c
AM
4369+ h_inode = file_inode(hf);
4370+ put_write_access(h_inode);
c06a8ce3 4371+ __mnt_drop_write(hf->f_path.mnt);
eca34b5c
AM
4372+ if ((hf->f_mode & (FMODE_READ | FMODE_WRITE))
4373+ == FMODE_READ)
4374+ i_readcount_inc(h_inode);
1facf9fc 4375+ }
4376+ }
4377+
7f207e10
AM
4378+out_array:
4379+ au_farray_free(array, max);
4f0767ce 4380+out:
7f207e10 4381+ AuTraceErr(err);
1facf9fc 4382+ return err;
4383+}
4384+
4385+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4386+ int *do_refresh)
1facf9fc 4387+{
4388+ int err, rerr;
4389+ aufs_bindex_t bindex;
4390+ struct dentry *root;
4391+ struct au_branch *br;
076b876e 4392+ struct au_br_fhsm *bf;
1facf9fc 4393+
4394+ root = sb->s_root;
1facf9fc 4395+ bindex = au_find_dbindex(root, mod->h_root);
4396+ if (bindex < 0) {
4397+ if (remount)
4398+ return 0; /* success */
4399+ err = -ENOENT;
4a4d8108 4400+ pr_err("%s no such branch\n", mod->path);
1facf9fc 4401+ goto out;
4402+ }
4403+ AuDbg("bindex b%d\n", bindex);
4404+
5527c038 4405+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path);
1facf9fc 4406+ if (unlikely(err))
4407+ goto out;
4408+
4409+ br = au_sbr(sb, bindex);
86dc4139 4410+ AuDebugOn(mod->h_root != au_br_dentry(br));
1facf9fc 4411+ if (br->br_perm == mod->perm)
4412+ return 0; /* success */
4413+
076b876e
AM
4414+ /* pre-allocate for non-fhsm --> fhsm */
4415+ bf = NULL;
4416+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) {
4417+ err = au_fhsm_br_alloc(br);
4418+ if (unlikely(err))
4419+ goto out;
4420+ bf = br->br_fhsm;
4421+ br->br_fhsm = NULL;
4422+ }
4423+
1facf9fc 4424+ if (au_br_writable(br->br_perm)) {
4425+ /* remove whiteout base */
86dc4139 4426+ err = au_br_init_wh(sb, br, mod->perm);
1facf9fc 4427+ if (unlikely(err))
076b876e 4428+ goto out_bf;
1facf9fc 4429+
4430+ if (!au_br_writable(mod->perm)) {
4431+ /* rw --> ro, file might be mmapped */
4432+ DiMustNoWaiters(root);
5527c038 4433+ IiMustNoWaiters(d_inode(root));
1facf9fc 4434+ di_write_unlock(root);
4435+ err = au_br_mod_files_ro(sb, bindex);
4436+ /* aufs_write_lock() calls ..._child() */
4437+ di_write_lock_child(root);
4438+
4439+ if (unlikely(err)) {
4440+ rerr = -ENOMEM;
be52b249 4441+ br->br_wbr = kzalloc(sizeof(*br->br_wbr),
1facf9fc 4442+ GFP_NOFS);
86dc4139
AM
4443+ if (br->br_wbr)
4444+ rerr = au_wbr_init(br, sb, br->br_perm);
1facf9fc 4445+ if (unlikely(rerr)) {
4446+ AuIOErr("nested error %d (%d)\n",
4447+ rerr, err);
4448+ br->br_perm = mod->perm;
4449+ }
4450+ }
4451+ }
4452+ } else if (au_br_writable(mod->perm)) {
4453+ /* ro --> rw */
4454+ err = -ENOMEM;
be52b249 4455+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS);
1facf9fc 4456+ if (br->br_wbr) {
86dc4139 4457+ err = au_wbr_init(br, sb, mod->perm);
1facf9fc 4458+ if (unlikely(err)) {
9f237c51 4459+ au_kfree_rcu(br->br_wbr);
1facf9fc 4460+ br->br_wbr = NULL;
4461+ }
4462+ }
4463+ }
076b876e
AM
4464+ if (unlikely(err))
4465+ goto out_bf;
4466+
4467+ if (au_br_fhsm(br->br_perm)) {
4468+ if (!au_br_fhsm(mod->perm)) {
4469+ /* fhsm --> non-fhsm */
4470+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 4471+ au_kfree_rcu(br->br_fhsm);
076b876e
AM
4472+ br->br_fhsm = NULL;
4473+ }
4474+ } else if (au_br_fhsm(mod->perm))
4475+ /* non-fhsm --> fhsm */
4476+ br->br_fhsm = bf;
4477+
076b876e
AM
4478+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
4479+ br->br_perm = mod->perm;
4480+ goto out; /* success */
1facf9fc 4481+
076b876e 4482+out_bf:
9f237c51 4483+ au_kfree_try_rcu(bf);
076b876e
AM
4484+out:
4485+ AuTraceErr(err);
4486+ return err;
4487+}
4488+
4489+/* ---------------------------------------------------------------------- */
4490+
4491+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs)
4492+{
4493+ int err;
4494+ struct kstatfs kstfs;
4495+
4496+ err = vfs_statfs(&br->br_path, &kstfs);
1facf9fc 4497+ if (!err) {
076b876e
AM
4498+ stfs->f_blocks = kstfs.f_blocks;
4499+ stfs->f_bavail = kstfs.f_bavail;
4500+ stfs->f_files = kstfs.f_files;
4501+ stfs->f_ffree = kstfs.f_ffree;
1facf9fc 4502+ }
4503+
1facf9fc 4504+ return err;
4505+}
7f207e10 4506diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
eca34b5c
AM
4507--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
4508+++ linux/fs/aufs/branch.h 2019-07-11 15:42:14.462237786 +0200
83b672a5 4509@@ -0,0 +1,366 @@
062440b3 4510+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 4511+/*
ba1aed25 4512+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 4513+ *
4514+ * This program, aufs is free software; you can redistribute it and/or modify
4515+ * it under the terms of the GNU General Public License as published by
4516+ * the Free Software Foundation; either version 2 of the License, or
4517+ * (at your option) any later version.
dece6358
AM
4518+ *
4519+ * This program is distributed in the hope that it will be useful,
4520+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4521+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4522+ * GNU General Public License for more details.
4523+ *
4524+ * You should have received a copy of the GNU General Public License
523b37e3 4525+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4526+ */
4527+
4528+/*
4529+ * branch filesystems and xino for them
4530+ */
4531+
4532+#ifndef __AUFS_BRANCH_H__
4533+#define __AUFS_BRANCH_H__
4534+
4535+#ifdef __KERNEL__
4536+
1facf9fc 4537+#include <linux/mount.h>
8b6a4947 4538+#include "dirren.h"
4a4d8108 4539+#include "dynop.h"
acd2b654 4540+#include "lcnt.h"
1facf9fc 4541+#include "rwsem.h"
4542+#include "super.h"
4543+
4544+/* ---------------------------------------------------------------------- */
4545+
4546+/* a xino file */
062440b3 4547+struct au_xino {
acd2b654
AM
4548+ struct file **xi_file;
4549+ unsigned int xi_nfile;
4550+
521ced18
JR
4551+ struct {
4552+ spinlock_t spin;
4553+ ino_t *array;
4554+ int total;
4555+ /* reserved for future use */
4556+ /* unsigned long *bitmap; */
4557+ wait_queue_head_t wqh;
4558+ } xi_nondir;
1facf9fc 4559+
acd2b654 4560+ struct mutex xi_mtx; /* protects xi_file array */
9f237c51 4561+ struct hlist_bl_head xi_writing;
acd2b654 4562+
062440b3 4563+ atomic_t xi_truncating;
1facf9fc 4564+
062440b3 4565+ struct kref xi_kref;
1facf9fc 4566+};
4567+
076b876e
AM
4568+/* File-based Hierarchical Storage Management */
4569+struct au_br_fhsm {
4570+#ifdef CONFIG_AUFS_FHSM
4571+ struct mutex bf_lock;
4572+ unsigned long bf_jiffy;
4573+ struct aufs_stfs bf_stfs;
4574+ int bf_readable;
4575+#endif
4576+};
4577+
1facf9fc 4578+/* members for writable branch only */
4579+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
4580+struct au_wbr {
dece6358 4581+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 4582+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 4583+ atomic_t wbr_wh_running;
1facf9fc 4584+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
4585+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
4586+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
4587+
4588+ /* mfs mode */
4589+ unsigned long long wbr_bytes;
4590+};
4591+
4a4d8108
AM
4592+/* ext2 has 3 types of operations at least, ext3 has 4 */
4593+#define AuBrDynOp (AuDyLast * 4)
4594+
1716fcea
AM
4595+#ifdef CONFIG_AUFS_HFSNOTIFY
4596+/* support for asynchronous destruction */
4597+struct au_br_hfsnotify {
4598+ struct fsnotify_group *hfsn_group;
4599+};
4600+#endif
4601+
392086de
AM
4602+/* sysfs entries */
4603+struct au_brsysfs {
4604+ char name[16];
4605+ struct attribute attr;
4606+};
4607+
4608+enum {
4609+ AuBrSysfs_BR,
4610+ AuBrSysfs_BRID,
4611+ AuBrSysfs_Last
4612+};
4613+
1facf9fc 4614+/* protected by superblock rwsem */
4615+struct au_branch {
062440b3 4616+ struct au_xino *br_xino;
1facf9fc 4617+
4618+ aufs_bindex_t br_id;
4619+
4620+ int br_perm;
86dc4139 4621+ struct path br_path;
4a4d8108
AM
4622+ spinlock_t br_dykey_lock;
4623+ struct au_dykey *br_dykey[AuBrDynOp];
acd2b654
AM
4624+ au_lcnt_t br_nfiles; /* opened files */
4625+ au_lcnt_t br_count; /* in-use for other */
1facf9fc 4626+
4627+ struct au_wbr *br_wbr;
076b876e 4628+ struct au_br_fhsm *br_fhsm;
1facf9fc 4629+
027c5e7a 4630+#ifdef CONFIG_AUFS_HFSNOTIFY
1716fcea 4631+ struct au_br_hfsnotify *br_hfsn;
027c5e7a
AM
4632+#endif
4633+
1facf9fc 4634+#ifdef CONFIG_SYSFS
392086de
AM
4635+ /* entries under sysfs per mount-point */
4636+ struct au_brsysfs br_sysfs[AuBrSysfs_Last];
1facf9fc 4637+#endif
8b6a4947 4638+
062440b3
AM
4639+#ifdef CONFIG_DEBUG_FS
4640+ struct dentry *br_dbgaufs; /* xino */
4641+#endif
4642+
8b6a4947 4643+ struct au_dr_br br_dirren;
1facf9fc 4644+};
4645+
4646+/* ---------------------------------------------------------------------- */
4647+
86dc4139
AM
4648+static inline struct vfsmount *au_br_mnt(struct au_branch *br)
4649+{
4650+ return br->br_path.mnt;
4651+}
4652+
4653+static inline struct dentry *au_br_dentry(struct au_branch *br)
4654+{
4655+ return br->br_path.dentry;
4656+}
4657+
4658+static inline struct super_block *au_br_sb(struct au_branch *br)
4659+{
4660+ return au_br_mnt(br)->mnt_sb;
4661+}
4662+
1facf9fc 4663+static inline int au_br_rdonly(struct au_branch *br)
4664+{
8b6a4947 4665+ return (sb_rdonly(au_br_sb(br))
1facf9fc 4666+ || !au_br_writable(br->br_perm))
4667+ ? -EROFS : 0;
4668+}
4669+
4a4d8108 4670+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 4671+{
4a4d8108 4672+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 4673+ return !(brperm & AuBrPerm_RR);
1facf9fc 4674+#else
4675+ return 0;
4676+#endif
4677+}
4678+
b912730e
AM
4679+static inline int au_br_test_oflag(int oflag, struct au_branch *br)
4680+{
4681+ int err, exec_flag;
4682+
4683+ err = 0;
4684+ exec_flag = oflag & __FMODE_EXEC;
79b8bda9 4685+ if (unlikely(exec_flag && path_noexec(&br->br_path)))
b912730e
AM
4686+ err = -EACCES;
4687+
4688+ return err;
4689+}
4690+
062440b3
AM
4691+static inline void au_xino_get(struct au_branch *br)
4692+{
4693+ struct au_xino *xi;
4694+
4695+ xi = br->br_xino;
4696+ if (xi)
4697+ kref_get(&xi->xi_kref);
4698+}
4699+
4700+static inline int au_xino_count(struct au_branch *br)
4701+{
4702+ int v;
4703+ struct au_xino *xi;
4704+
4705+ v = 0;
4706+ xi = br->br_xino;
4707+ if (xi)
4708+ v = kref_read(&xi->xi_kref);
4709+
4710+ return v;
4711+}
4712+
1facf9fc 4713+/* ---------------------------------------------------------------------- */
4714+
4715+/* branch.c */
4716+struct au_sbinfo;
4717+void au_br_free(struct au_sbinfo *sinfo);
4718+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
4719+struct au_opt_add;
4720+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
4721+struct au_opt_del;
4722+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
4723+long au_ibusy_ioctl(struct file *file, unsigned long arg);
4724+#ifdef CONFIG_COMPAT
4725+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
4726+#endif
1facf9fc 4727+struct au_opt_mod;
4728+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4729+ int *do_refresh);
076b876e
AM
4730+struct aufs_stfs;
4731+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
1facf9fc 4732+
4733+/* xino.c */
4734+static const loff_t au_loff_max = LLONG_MAX;
4735+
acd2b654 4736+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry);
83b672a5
AM
4737+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
4738+ int wbrtop);
062440b3
AM
4739+struct file *au_xino_create2(struct super_block *sb, struct path *base,
4740+ struct file *copy_src);
acd2b654
AM
4741+struct au_xi_new {
4742+ struct au_xino *xi; /* switch between xino and xigen */
4743+ int idx;
4744+ struct path *base;
4745+ struct file *copy_src;
4746+};
4747+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew);
062440b3
AM
4748+
4749+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4750+ ino_t *ino);
4751+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4752+ ino_t ino);
5527c038 4753+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size,
1facf9fc 4754+ loff_t *pos);
5527c038
JR
4755+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
4756+ size_t size, loff_t *pos);
062440b3
AM
4757+
4758+int au_xib_trunc(struct super_block *sb);
acd2b654 4759+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin);
1facf9fc 4760+
acd2b654 4761+struct au_xino *au_xino_alloc(unsigned int nfile);
062440b3 4762+int au_xino_put(struct au_branch *br);
acd2b654 4763+struct file *au_xino_file1(struct au_xino *xi);
062440b3 4764+
1facf9fc 4765+struct au_opt_xino;
1facf9fc 4766+void au_xino_clr(struct super_block *sb);
062440b3 4767+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount);
1facf9fc 4768+struct file *au_xino_def(struct super_block *sb);
062440b3
AM
4769+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino,
4770+ struct path *base);
4771+
4772+ino_t au_xino_new_ino(struct super_block *sb);
4773+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 4774+
521ced18
JR
4775+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
4776+ ino_t h_ino, int idx);
4777+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4778+ int *idx);
4779+
062440b3
AM
4780+int au_xino_path(struct seq_file *seq, struct file *file);
4781+
1facf9fc 4782+/* ---------------------------------------------------------------------- */
4783+
acd2b654
AM
4784+/* @idx is signed to accept -1 meaning the first file */
4785+static inline struct file *au_xino_file(struct au_xino *xi, int idx)
4786+{
4787+ struct file *file;
4788+
4789+ file = NULL;
4790+ if (!xi)
4791+ goto out;
4792+
4793+ if (idx >= 0) {
4794+ if (idx < xi->xi_nfile)
4795+ file = xi->xi_file[idx];
4796+ } else
4797+ file = au_xino_file1(xi);
4798+
4799+out:
4800+ return file;
4801+}
4802+
4803+/* ---------------------------------------------------------------------- */
4804+
1facf9fc 4805+/* Superblock to branch */
4806+static inline
4807+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
4808+{
4809+ return au_sbr(sb, bindex)->br_id;
4810+}
4811+
4812+static inline
4813+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
4814+{
86dc4139 4815+ return au_br_mnt(au_sbr(sb, bindex));
1facf9fc 4816+}
4817+
4818+static inline
4819+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
4820+{
86dc4139 4821+ return au_br_sb(au_sbr(sb, bindex));
1facf9fc 4822+}
4823+
1facf9fc 4824+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
4825+{
4826+ return au_sbr(sb, bindex)->br_perm;
4827+}
4828+
4829+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
4830+{
4831+ return au_br_whable(au_sbr_perm(sb, bindex));
4832+}
4833+
4834+/* ---------------------------------------------------------------------- */
4835+
8b6a4947
AM
4836+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem)
4837+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem)
4838+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem)
4839+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem)
1facf9fc 4840+/*
8b6a4947
AM
4841+#define wbr_wh_read_trylock_nested(wbr) \
4842+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem)
4843+#define wbr_wh_write_trylock_nested(wbr) \
4844+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem)
4845+*/
1facf9fc 4846+
8b6a4947
AM
4847+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem)
4848+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem)
4849+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem)
4850+
4851+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem)
4852+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem)
4853+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem)
dece6358 4854+
076b876e
AM
4855+/* ---------------------------------------------------------------------- */
4856+
4857+#ifdef CONFIG_AUFS_FHSM
4858+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm)
4859+{
4860+ mutex_init(&brfhsm->bf_lock);
4861+ brfhsm->bf_jiffy = 0;
4862+ brfhsm->bf_readable = 0;
4863+}
4864+
4865+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm)
4866+{
4867+ mutex_destroy(&brfhsm->bf_lock);
4868+}
4869+#else
4870+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm)
4871+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm)
4872+#endif
4873+
1facf9fc 4874+#endif /* __KERNEL__ */
4875+#endif /* __AUFS_BRANCH_H__ */
7f207e10 4876diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
eca34b5c
AM
4877--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
4878+++ linux/fs/aufs/conf.mk 2019-07-11 15:42:14.462237786 +0200
2121bcd9
AM
4879@@ -0,0 +1,40 @@
4880+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
4881+
4882+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
4883+
4884+define AuConf
4885+ifdef ${1}
4886+AuConfStr += ${1}=${${1}}
4887+endif
4888+endef
4889+
b752ccd1 4890+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 4891+ SBILIST \
7f207e10 4892+ HNOTIFY HFSNOTIFY \
4a4d8108 4893+ EXPORT INO_T_64 \
c1595e42 4894+ XATTR \
076b876e 4895+ FHSM \
4a4d8108 4896+ RDU \
8b6a4947 4897+ DIRREN \
4a4d8108
AM
4898+ SHWH \
4899+ BR_RAMFS \
4900+ BR_FUSE POLL \
4901+ BR_HFSPLUS \
4902+ BDEV_LOOP \
b752ccd1
AM
4903+ DEBUG MAGIC_SYSRQ
4904+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
4905+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
4906+
4907+AuConfName = ${obj}/conf.str
4908+${AuConfName}.tmp: FORCE
4909+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
4910+${AuConfName}: ${AuConfName}.tmp
4911+ @diff -q $< $@ > /dev/null 2>&1 || { \
4912+ echo ' GEN ' $@; \
4913+ cp -p $< $@; \
4914+ }
4915+FORCE:
4916+clean-files += ${AuConfName} ${AuConfName}.tmp
4917+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
4918+
4919+-include ${srctree}/${src}/conf_priv.mk
7f207e10 4920diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
eca34b5c
AM
4921--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
4922+++ linux/fs/aufs/cpup.c 2019-07-11 15:42:14.462237786 +0200
9f237c51 4923@@ -0,0 +1,1458 @@
cd7a4cd9 4924+// SPDX-License-Identifier: GPL-2.0
1facf9fc 4925+/*
ba1aed25 4926+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 4927+ *
4928+ * This program, aufs is free software; you can redistribute it and/or modify
4929+ * it under the terms of the GNU General Public License as published by
4930+ * the Free Software Foundation; either version 2 of the License, or
4931+ * (at your option) any later version.
dece6358
AM
4932+ *
4933+ * This program is distributed in the hope that it will be useful,
4934+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4935+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4936+ * GNU General Public License for more details.
4937+ *
4938+ * You should have received a copy of the GNU General Public License
523b37e3 4939+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4940+ */
4941+
4942+/*
4943+ * copy-up functions, see wbr_policy.c for copy-down
4944+ */
4945+
4946+#include <linux/fs_stack.h>
dece6358 4947+#include <linux/mm.h>
8cdd5066 4948+#include <linux/task_work.h>
1facf9fc 4949+#include "aufs.h"
4950+
86dc4139 4951+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags)
1facf9fc 4952+{
4953+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
367653fa 4954+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT;
1facf9fc 4955+
86dc4139
AM
4956+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags));
4957+
4958+ dst->i_flags |= iflags & ~mask;
1facf9fc 4959+ if (au_test_fs_notime(dst->i_sb))
4960+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
4961+}
4962+
4963+void au_cpup_attr_timesizes(struct inode *inode)
4964+{
4965+ struct inode *h_inode;
4966+
5afbbe0d 4967+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4968+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 4969+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 4970+}
4971+
4972+void au_cpup_attr_nlink(struct inode *inode, int force)
4973+{
4974+ struct inode *h_inode;
4975+ struct super_block *sb;
5afbbe0d 4976+ aufs_bindex_t bindex, bbot;
1facf9fc 4977+
4978+ sb = inode->i_sb;
5afbbe0d 4979+ bindex = au_ibtop(inode);
1facf9fc 4980+ h_inode = au_h_iptr(inode, bindex);
4981+ if (!force
4982+ && !S_ISDIR(h_inode->i_mode)
4983+ && au_opt_test(au_mntflags(sb), PLINK)
4984+ && au_plink_test(inode))
4985+ return;
4986+
7eafdf33
AM
4987+ /*
4988+ * 0 can happen in revalidating.
38d290e6
JR
4989+ * h_inode->i_mutex may not be held here, but it is harmless since once
4990+ * i_nlink reaches 0, it will never become positive except O_TMPFILE
4991+ * case.
4992+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause
4993+ * the incorrect link count.
7eafdf33 4994+ */
92d182d2 4995+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 4996+
4997+ /*
4998+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
4999+ * it may includes whplink directory.
5000+ */
5001+ if (S_ISDIR(h_inode->i_mode)) {
5afbbe0d
AM
5002+ bbot = au_ibbot(inode);
5003+ for (bindex++; bindex <= bbot; bindex++) {
1facf9fc 5004+ h_inode = au_h_iptr(inode, bindex);
5005+ if (h_inode)
5006+ au_add_nlink(inode, h_inode);
5007+ }
5008+ }
5009+}
5010+
5011+void au_cpup_attr_changeable(struct inode *inode)
5012+{
5013+ struct inode *h_inode;
5014+
5afbbe0d 5015+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 5016+ inode->i_mode = h_inode->i_mode;
5017+ inode->i_uid = h_inode->i_uid;
5018+ inode->i_gid = h_inode->i_gid;
5019+ au_cpup_attr_timesizes(inode);
86dc4139 5020+ au_cpup_attr_flags(inode, h_inode->i_flags);
1facf9fc 5021+}
5022+
5023+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
5024+{
5025+ struct au_iinfo *iinfo = au_ii(inode);
5026+
1308ab2a 5027+ IiMustWriteLock(inode);
5028+
1facf9fc 5029+ iinfo->ii_higen = h_inode->i_generation;
5030+ iinfo->ii_hsb1 = h_inode->i_sb;
5031+}
5032+
5033+void au_cpup_attr_all(struct inode *inode, int force)
5034+{
5035+ struct inode *h_inode;
5036+
5afbbe0d 5037+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 5038+ au_cpup_attr_changeable(inode);
5039+ if (inode->i_nlink > 0)
5040+ au_cpup_attr_nlink(inode, force);
5041+ inode->i_rdev = h_inode->i_rdev;
5042+ inode->i_blkbits = h_inode->i_blkbits;
5043+ au_cpup_igen(inode, h_inode);
5044+}
5045+
5046+/* ---------------------------------------------------------------------- */
5047+
5048+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
5049+
5050+/* keep the timestamps of the parent dir when cpup */
5051+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
5052+ struct path *h_path)
5053+{
5054+ struct inode *h_inode;
5055+
5056+ dt->dt_dentry = dentry;
5057+ dt->dt_h_path = *h_path;
5527c038 5058+ h_inode = d_inode(h_path->dentry);
1facf9fc 5059+ dt->dt_atime = h_inode->i_atime;
5060+ dt->dt_mtime = h_inode->i_mtime;
5061+ /* smp_mb(); */
5062+}
5063+
5064+void au_dtime_revert(struct au_dtime *dt)
5065+{
5066+ struct iattr attr;
5067+ int err;
5068+
5069+ attr.ia_atime = dt->dt_atime;
5070+ attr.ia_mtime = dt->dt_mtime;
5071+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
5072+ | ATTR_ATIME | ATTR_ATIME_SET;
5073+
523b37e3
AM
5074+ /* no delegation since this is a directory */
5075+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL);
1facf9fc 5076+ if (unlikely(err))
0c3ec466 5077+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 5078+}
5079+
5080+/* ---------------------------------------------------------------------- */
5081+
86dc4139
AM
5082+/* internal use only */
5083+struct au_cpup_reg_attr {
5084+ int valid;
5085+ struct kstat st;
5086+ unsigned int iflags; /* inode->i_flags */
5087+};
5088+
1facf9fc 5089+static noinline_for_stack
86dc4139
AM
5090+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
5091+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5092+{
c1595e42 5093+ int err, sbits, icex;
7e9cd9fe
AM
5094+ unsigned int mnt_flags;
5095+ unsigned char verbose;
1facf9fc 5096+ struct iattr ia;
5097+ struct path h_path;
1308ab2a 5098+ struct inode *h_isrc, *h_idst;
86dc4139 5099+ struct kstat *h_st;
c1595e42 5100+ struct au_branch *br;
1facf9fc 5101+
5102+ h_path.dentry = au_h_dptr(dst, bindex);
5527c038 5103+ h_idst = d_inode(h_path.dentry);
c1595e42
JR
5104+ br = au_sbr(dst->d_sb, bindex);
5105+ h_path.mnt = au_br_mnt(br);
5527c038 5106+ h_isrc = d_inode(h_src);
1308ab2a 5107+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 5108+ | ATTR_ATIME | ATTR_MTIME
5109+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
86dc4139
AM
5110+ if (h_src_attr && h_src_attr->valid) {
5111+ h_st = &h_src_attr->st;
5112+ ia.ia_uid = h_st->uid;
5113+ ia.ia_gid = h_st->gid;
5114+ ia.ia_atime = h_st->atime;
5115+ ia.ia_mtime = h_st->mtime;
5116+ if (h_idst->i_mode != h_st->mode
5117+ && !S_ISLNK(h_idst->i_mode)) {
5118+ ia.ia_valid |= ATTR_MODE;
5119+ ia.ia_mode = h_st->mode;
5120+ }
5121+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID));
5122+ au_cpup_attr_flags(h_idst, h_src_attr->iflags);
5123+ } else {
5124+ ia.ia_uid = h_isrc->i_uid;
5125+ ia.ia_gid = h_isrc->i_gid;
5126+ ia.ia_atime = h_isrc->i_atime;
5127+ ia.ia_mtime = h_isrc->i_mtime;
5128+ if (h_idst->i_mode != h_isrc->i_mode
5129+ && !S_ISLNK(h_idst->i_mode)) {
5130+ ia.ia_valid |= ATTR_MODE;
5131+ ia.ia_mode = h_isrc->i_mode;
5132+ }
5133+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
5134+ au_cpup_attr_flags(h_idst, h_isrc->i_flags);
1308ab2a 5135+ }
523b37e3
AM
5136+ /* no delegation since it is just created */
5137+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 5138+
5139+ /* is this nfs only? */
5140+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
5141+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
5142+ ia.ia_mode = h_isrc->i_mode;
523b37e3 5143+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 5144+ }
5145+
c1595e42 5146+ icex = br->br_perm & AuBrAttr_ICEX;
7e9cd9fe
AM
5147+ if (!err) {
5148+ mnt_flags = au_mntflags(dst->d_sb);
5149+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
5150+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose);
5151+ }
c1595e42 5152+
1facf9fc 5153+ return err;
5154+}
5155+
5156+/* ---------------------------------------------------------------------- */
5157+
5158+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
5159+ char *buf, unsigned long blksize)
5160+{
5161+ int err;
5162+ size_t sz, rbytes, wbytes;
5163+ unsigned char all_zero;
5164+ char *p, *zp;
febd17d6 5165+ struct inode *h_inode;
1facf9fc 5166+ /* reduce stack usage */
5167+ struct iattr *ia;
5168+
5169+ zp = page_address(ZERO_PAGE(0));
5170+ if (unlikely(!zp))
5171+ return -ENOMEM; /* possible? */
5172+
5173+ err = 0;
5174+ all_zero = 0;
5175+ while (len) {
5176+ AuDbg("len %lld\n", len);
5177+ sz = blksize;
5178+ if (len < blksize)
5179+ sz = len;
5180+
5181+ rbytes = 0;
5182+ /* todo: signal_pending? */
5183+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
5184+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
5185+ err = rbytes;
5186+ }
5187+ if (unlikely(err < 0))
5188+ break;
5189+
5190+ all_zero = 0;
5191+ if (len >= rbytes && rbytes == blksize)
5192+ all_zero = !memcmp(buf, zp, rbytes);
5193+ if (!all_zero) {
5194+ wbytes = rbytes;
5195+ p = buf;
5196+ while (wbytes) {
5197+ size_t b;
5198+
5199+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
5200+ err = b;
5201+ /* todo: signal_pending? */
5202+ if (unlikely(err == -EAGAIN || err == -EINTR))
5203+ continue;
5204+ if (unlikely(err < 0))
5205+ break;
5206+ wbytes -= b;
5207+ p += b;
5208+ }
392086de
AM
5209+ if (unlikely(err < 0))
5210+ break;
1facf9fc 5211+ } else {
5212+ loff_t res;
5213+
5214+ AuLabel(hole);
5215+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
5216+ err = res;
5217+ if (unlikely(res < 0))
5218+ break;
5219+ }
5220+ len -= rbytes;
5221+ err = 0;
5222+ }
5223+
5224+ /* the last block may be a hole */
5225+ if (!err && all_zero) {
5226+ AuLabel(last hole);
5227+
5228+ err = 1;
2000de60 5229+ if (au_test_nfs(dst->f_path.dentry->d_sb)) {
1facf9fc 5230+ /* nfs requires this step to make last hole */
5231+ /* is this only nfs? */
5232+ do {
5233+ /* todo: signal_pending? */
5234+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
5235+ } while (err == -EAGAIN || err == -EINTR);
5236+ if (err == 1)
5237+ dst->f_pos--;
5238+ }
5239+
5240+ if (err == 1) {
5241+ ia = (void *)buf;
5242+ ia->ia_size = dst->f_pos;
5243+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
5244+ ia->ia_file = dst;
febd17d6
JR
5245+ h_inode = file_inode(dst);
5246+ inode_lock_nested(h_inode, AuLsc_I_CHILD2);
523b37e3
AM
5247+ /* no delegation since it is just created */
5248+ err = vfsub_notify_change(&dst->f_path, ia,
5249+ /*delegated*/NULL);
febd17d6 5250+ inode_unlock(h_inode);
1facf9fc 5251+ }
5252+ }
5253+
5254+ return err;
5255+}
5256+
5257+int au_copy_file(struct file *dst, struct file *src, loff_t len)
5258+{
5259+ int err;
5260+ unsigned long blksize;
5261+ unsigned char do_kfree;
5262+ char *buf;
9f237c51 5263+ struct super_block *h_sb;
1facf9fc 5264+
5265+ err = -ENOMEM;
9f237c51
AM
5266+ h_sb = file_inode(dst)->i_sb;
5267+ blksize = h_sb->s_blocksize;
1facf9fc 5268+ if (!blksize || PAGE_SIZE < blksize)
5269+ blksize = PAGE_SIZE;
5270+ AuDbg("blksize %lu\n", blksize);
5271+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
5272+ if (do_kfree)
5273+ buf = kmalloc(blksize, GFP_NOFS);
5274+ else
5275+ buf = (void *)__get_free_page(GFP_NOFS);
5276+ if (unlikely(!buf))
5277+ goto out;
5278+
5279+ if (len > (1 << 22))
5280+ AuDbg("copying a large file %lld\n", (long long)len);
5281+
5282+ src->f_pos = 0;
5283+ dst->f_pos = 0;
5284+ err = au_do_copy_file(dst, src, len, buf, blksize);
9f237c51
AM
5285+ if (do_kfree) {
5286+ AuDebugOn(!au_kfree_do_sz_test(blksize));
5287+ au_kfree_do_rcu(buf);
5288+ } else
1c60b727 5289+ free_page((unsigned long)buf);
1facf9fc 5290+
4f0767ce 5291+out:
1facf9fc 5292+ return err;
5293+}
5294+
1c60b727
AM
5295+static int au_do_copy(struct file *dst, struct file *src, loff_t len)
5296+{
5297+ int err;
5298+ struct super_block *h_src_sb;
5299+ struct inode *h_src_inode;
5300+
5301+ h_src_inode = file_inode(src);
5302+ h_src_sb = h_src_inode->i_sb;
5303+
5304+ /* XFS acquires inode_lock */
5305+ if (!au_test_xfs(h_src_sb))
5306+ err = au_copy_file(dst, src, len);
5307+ else {
3c1bdaff 5308+ inode_unlock_shared(h_src_inode);
1c60b727 5309+ err = au_copy_file(dst, src, len);
be118d29 5310+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727
AM
5311+ }
5312+
5313+ return err;
5314+}
5315+
5316+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len)
5317+{
5318+ int err;
9f237c51 5319+ loff_t lo;
1c60b727
AM
5320+ struct super_block *h_src_sb;
5321+ struct inode *h_src_inode;
5322+
5323+ h_src_inode = file_inode(src);
5324+ h_src_sb = h_src_inode->i_sb;
5325+ if (h_src_sb != file_inode(dst)->i_sb
9f237c51 5326+ || !dst->f_op->remap_file_range) {
1c60b727
AM
5327+ err = au_do_copy(dst, src, len);
5328+ goto out;
5329+ }
5330+
5331+ if (!au_test_nfs(h_src_sb)) {
3c1bdaff 5332+ inode_unlock_shared(h_src_inode);
9f237c51 5333+ lo = vfsub_clone_file_range(src, dst, len);
be118d29 5334+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727 5335+ } else
9f237c51
AM
5336+ lo = vfsub_clone_file_range(src, dst, len);
5337+ if (lo == len) {
5338+ err = 0;
5339+ goto out; /* success */
5340+ } else if (lo >= 0)
5341+ /* todo: possible? */
5342+ /* paritially succeeded */
5343+ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len);
5344+ else if (lo != -EOPNOTSUPP) {
5345+ /* older XFS has a condition in cloning */
5346+ err = lo;
1c60b727 5347+ goto out;
9f237c51 5348+ }
1c60b727
AM
5349+
5350+ /* the backend fs on NFS may not support cloning */
5351+ err = au_do_copy(dst, src, len);
5352+
5353+out:
5354+ AuTraceErr(err);
5355+ return err;
5356+}
5357+
1facf9fc 5358+/*
5359+ * to support a sparse file which is opened with O_APPEND,
5360+ * we need to close the file.
5361+ */
c2b27bf2 5362+static int au_cp_regular(struct au_cp_generic *cpg)
1facf9fc 5363+{
5364+ int err, i;
5365+ enum { SRC, DST };
5366+ struct {
5367+ aufs_bindex_t bindex;
5368+ unsigned int flags;
5369+ struct dentry *dentry;
392086de 5370+ int force_wr;
1facf9fc 5371+ struct file *file;
1facf9fc 5372+ } *f, file[] = {
5373+ {
c2b27bf2 5374+ .bindex = cpg->bsrc,
1facf9fc 5375+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
1facf9fc 5376+ },
5377+ {
c2b27bf2 5378+ .bindex = cpg->bdst,
1facf9fc 5379+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
392086de 5380+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST),
1facf9fc 5381+ }
5382+ };
acd2b654 5383+ struct au_branch *br;
521ced18 5384+ struct super_block *sb, *h_src_sb;
e2f27e51 5385+ struct inode *h_src_inode;
8cdd5066 5386+ struct task_struct *tsk = current;
1facf9fc 5387+
5388+ /* bsrc branch can be ro/rw. */
c2b27bf2 5389+ sb = cpg->dentry->d_sb;
1facf9fc 5390+ f = file;
5391+ for (i = 0; i < 2; i++, f++) {
c2b27bf2
AM
5392+ f->dentry = au_h_dptr(cpg->dentry, f->bindex);
5393+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags,
392086de 5394+ /*file*/NULL, f->force_wr);
9f237c51
AM
5395+ if (IS_ERR(f->file)) {
5396+ err = PTR_ERR(f->file);
5397+ if (i == SRC)
5398+ goto out;
5399+ else
5400+ goto out_src;
5401+ }
1facf9fc 5402+ }
5403+
5404+ /* try stopping to update while we copyup */
e2f27e51 5405+ h_src_inode = d_inode(file[SRC].dentry);
521ced18
JR
5406+ h_src_sb = h_src_inode->i_sb;
5407+ if (!au_test_nfs(h_src_sb))
e2f27e51 5408+ IMustLock(h_src_inode);
1c60b727 5409+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len);
1facf9fc 5410+
8cdd5066
JR
5411+ /* i wonder if we had O_NO_DELAY_FPUT flag */
5412+ if (tsk->flags & PF_KTHREAD)
5413+ __fput_sync(file[DST].file);
5414+ else {
062440b3 5415+ /* it happened actually */
8cdd5066
JR
5416+ fput(file[DST].file);
5417+ /*
5418+ * too bad.
5419+ * we have to call both since we don't know which place the file
5420+ * was added to.
5421+ */
5422+ task_work_run();
5423+ flush_delayed_fput();
5424+ }
acd2b654
AM
5425+ br = au_sbr(sb, file[DST].bindex);
5426+ au_lcnt_dec(&br->br_nfiles);
523b37e3 5427+
4f0767ce 5428+out_src:
1facf9fc 5429+ fput(file[SRC].file);
acd2b654
AM
5430+ br = au_sbr(sb, file[SRC].bindex);
5431+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 5432+out:
1facf9fc 5433+ return err;
5434+}
5435+
c2b27bf2 5436+static int au_do_cpup_regular(struct au_cp_generic *cpg,
86dc4139 5437+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5438+{
5439+ int err, rerr;
5440+ loff_t l;
86dc4139 5441+ struct path h_path;
38d290e6 5442+ struct inode *h_src_inode, *h_dst_inode;
1facf9fc 5443+
5444+ err = 0;
5527c038 5445+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc);
86dc4139 5446+ l = i_size_read(h_src_inode);
c2b27bf2
AM
5447+ if (cpg->len == -1 || l < cpg->len)
5448+ cpg->len = l;
5449+ if (cpg->len) {
86dc4139 5450+ /* try stopping to update while we are referencing */
be118d29 5451+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
c2b27bf2 5452+ au_pin_hdir_unlock(cpg->pin);
1facf9fc 5453+
c2b27bf2
AM
5454+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5455+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc);
86dc4139 5456+ h_src_attr->iflags = h_src_inode->i_flags;
5527c038 5457+ if (!au_test_nfs(h_src_inode->i_sb))
521ced18 5458+ err = vfsub_getattr(&h_path, &h_src_attr->st);
5527c038 5459+ else {
3c1bdaff 5460+ inode_unlock_shared(h_src_inode);
521ced18 5461+ err = vfsub_getattr(&h_path, &h_src_attr->st);
be118d29 5462+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
5527c038 5463+ }
86dc4139 5464+ if (unlikely(err)) {
3c1bdaff 5465+ inode_unlock_shared(h_src_inode);
86dc4139
AM
5466+ goto out;
5467+ }
5468+ h_src_attr->valid = 1;
e2f27e51
AM
5469+ if (!au_test_nfs(h_src_inode->i_sb)) {
5470+ err = au_cp_regular(cpg);
3c1bdaff 5471+ inode_unlock_shared(h_src_inode);
e2f27e51 5472+ } else {
3c1bdaff 5473+ inode_unlock_shared(h_src_inode);
e2f27e51
AM
5474+ err = au_cp_regular(cpg);
5475+ }
c2b27bf2 5476+ rerr = au_pin_hdir_relock(cpg->pin);
86dc4139
AM
5477+ if (!err && rerr)
5478+ err = rerr;
1facf9fc 5479+ }
38d290e6
JR
5480+ if (!err && (h_src_inode->i_state & I_LINKABLE)) {
5481+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst);
5527c038 5482+ h_dst_inode = d_inode(h_path.dentry);
38d290e6
JR
5483+ spin_lock(&h_dst_inode->i_lock);
5484+ h_dst_inode->i_state |= I_LINKABLE;
5485+ spin_unlock(&h_dst_inode->i_lock);
5486+ }
1facf9fc 5487+
4f0767ce 5488+out:
1facf9fc 5489+ return err;
5490+}
5491+
5492+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
5493+ struct inode *h_dir)
5494+{
5495+ int err, symlen;
5496+ mm_segment_t old_fs;
b752ccd1
AM
5497+ union {
5498+ char *k;
5499+ char __user *u;
5500+ } sym;
1facf9fc 5501+
5502+ err = -ENOMEM;
537831f9 5503+ sym.k = (void *)__get_free_page(GFP_NOFS);
b752ccd1 5504+ if (unlikely(!sym.k))
1facf9fc 5505+ goto out;
5506+
9dbd164d 5507+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
1facf9fc 5508+ old_fs = get_fs();
5509+ set_fs(KERNEL_DS);
a2654f78 5510+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX);
1facf9fc 5511+ err = symlen;
5512+ set_fs(old_fs);
5513+
5514+ if (symlen > 0) {
b752ccd1
AM
5515+ sym.k[symlen] = 0;
5516+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 5517+ }
1c60b727 5518+ free_page((unsigned long)sym.k);
1facf9fc 5519+
4f0767ce 5520+out:
1facf9fc 5521+ return err;
5522+}
5523+
8cdd5066
JR
5524+/*
5525+ * regardless 'acl' option, reset all ACL.
5526+ * All ACL will be copied up later from the original entry on the lower branch.
5527+ */
5528+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode)
5529+{
5530+ int err;
5531+ struct dentry *h_dentry;
5532+ struct inode *h_inode;
5533+
5534+ h_dentry = h_path->dentry;
5535+ h_inode = d_inode(h_dentry);
5536+ /* forget_all_cached_acls(h_inode)); */
5537+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS);
5538+ AuTraceErr(err);
5539+ if (err == -EOPNOTSUPP)
5540+ err = 0;
5541+ if (!err)
5542+ err = vfsub_acl_chmod(h_inode, mode);
5543+
5544+ AuTraceErr(err);
5545+ return err;
5546+}
5547+
5548+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent,
5549+ struct inode *h_dir, struct path *h_path)
5550+{
5551+ int err;
5552+ struct inode *dir, *inode;
5553+
5554+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT);
5555+ AuTraceErr(err);
5556+ if (err == -EOPNOTSUPP)
5557+ err = 0;
5558+ if (unlikely(err))
5559+ goto out;
5560+
5561+ /*
5562+ * strange behaviour from the users view,
acd2b654 5563+ * particularly setattr case
8cdd5066
JR
5564+ */
5565+ dir = d_inode(dst_parent);
5afbbe0d 5566+ if (au_ibtop(dir) == cpg->bdst)
8cdd5066
JR
5567+ au_cpup_attr_nlink(dir, /*force*/1);
5568+ inode = d_inode(cpg->dentry);
5569+ au_cpup_attr_nlink(inode, /*force*/1);
5570+
5571+out:
5572+ return err;
5573+}
5574+
1facf9fc 5575+static noinline_for_stack
c2b27bf2 5576+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent,
86dc4139 5577+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5578+{
5579+ int err;
5580+ umode_t mode;
5581+ unsigned int mnt_flags;
076b876e 5582+ unsigned char isdir, isreg, force;
c2b27bf2 5583+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5584+ struct au_dtime dt;
5585+ struct path h_path;
5586+ struct dentry *h_src, *h_dst, *h_parent;
8cdd5066 5587+ struct inode *h_inode, *h_dir;
1facf9fc 5588+ struct super_block *sb;
5589+
5590+ /* bsrc branch can be ro/rw. */
c2b27bf2 5591+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038
JR
5592+ h_inode = d_inode(h_src);
5593+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc));
1facf9fc 5594+
5595+ /* try stopping to be referenced while we are creating */
c2b27bf2
AM
5596+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
5597+ if (au_ftest_cpup(cpg->flags, RENAME))
86dc4139
AM
5598+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX,
5599+ AUFS_WH_PFX_LEN));
1facf9fc 5600+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5601+ h_dir = d_inode(h_parent);
1facf9fc 5602+ IMustLock(h_dir);
5603+ AuDebugOn(h_parent != h_dst->d_parent);
5604+
c2b27bf2
AM
5605+ sb = cpg->dentry->d_sb;
5606+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst);
1facf9fc 5607+ if (do_dt) {
5608+ h_path.dentry = h_parent;
5609+ au_dtime_store(&dt, dst_parent, &h_path);
5610+ }
5611+ h_path.dentry = h_dst;
5612+
076b876e 5613+ isreg = 0;
1facf9fc 5614+ isdir = 0;
5615+ mode = h_inode->i_mode;
5616+ switch (mode & S_IFMT) {
5617+ case S_IFREG:
076b876e 5618+ isreg = 1;
cd7a4cd9 5619+ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true);
1facf9fc 5620+ if (!err)
c2b27bf2 5621+ err = au_do_cpup_regular(cpg, h_src_attr);
1facf9fc 5622+ break;
5623+ case S_IFDIR:
5624+ isdir = 1;
5625+ err = vfsub_mkdir(h_dir, &h_path, mode);
8cdd5066
JR
5626+ if (!err)
5627+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path);
1facf9fc 5628+ break;
5629+ case S_IFLNK:
5630+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
5631+ break;
5632+ case S_IFCHR:
5633+ case S_IFBLK:
5634+ AuDebugOn(!capable(CAP_MKNOD));
5635+ /*FALLTHROUGH*/
5636+ case S_IFIFO:
5637+ case S_IFSOCK:
5638+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
5639+ break;
5640+ default:
5641+ AuIOErr("Unknown inode type 0%o\n", mode);
5642+ err = -EIO;
5643+ }
8cdd5066
JR
5644+ if (!err)
5645+ err = au_reset_acl(h_dir, &h_path, mode);
1facf9fc 5646+
5647+ mnt_flags = au_mntflags(sb);
5648+ if (!au_opt_test(mnt_flags, UDBA_NONE)
5649+ && !isdir
5650+ && au_opt_test(mnt_flags, XINO)
38d290e6
JR
5651+ && (h_inode->i_nlink == 1
5652+ || (h_inode->i_state & I_LINKABLE))
1facf9fc 5653+ /* todo: unnecessary? */
5527c038 5654+ /* && d_inode(cpg->dentry)->i_nlink == 1 */
c2b27bf2
AM
5655+ && cpg->bdst < cpg->bsrc
5656+ && !au_ftest_cpup(cpg->flags, KEEPLINO))
5657+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 5658+ /* ignore this error */
5659+
076b876e
AM
5660+ if (!err) {
5661+ force = 0;
5662+ if (isreg) {
5663+ force = !!cpg->len;
5664+ if (cpg->len == -1)
5665+ force = !!i_size_read(h_inode);
5666+ }
5667+ au_fhsm_wrote(sb, cpg->bdst, force);
5668+ }
5669+
1facf9fc 5670+ if (do_dt)
5671+ au_dtime_revert(&dt);
5672+ return err;
5673+}
5674+
392086de 5675+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path)
86dc4139
AM
5676+{
5677+ int err;
392086de 5678+ struct dentry *dentry, *h_dentry, *h_parent, *parent;
86dc4139 5679+ struct inode *h_dir;
392086de 5680+ aufs_bindex_t bdst;
86dc4139 5681+
392086de
AM
5682+ dentry = cpg->dentry;
5683+ bdst = cpg->bdst;
5684+ h_dentry = au_h_dptr(dentry, bdst);
5685+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) {
5686+ dget(h_dentry);
5687+ au_set_h_dptr(dentry, bdst, NULL);
5688+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
5689+ if (!err)
5690+ h_path->dentry = dget(au_h_dptr(dentry, bdst));
86dc4139 5691+ au_set_h_dptr(dentry, bdst, h_dentry);
392086de
AM
5692+ } else {
5693+ err = 0;
5694+ parent = dget_parent(dentry);
5695+ h_parent = au_h_dptr(parent, bdst);
5696+ dput(parent);
5697+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
5698+ if (IS_ERR(h_path->dentry))
5699+ err = PTR_ERR(h_path->dentry);
86dc4139 5700+ }
392086de
AM
5701+ if (unlikely(err))
5702+ goto out;
86dc4139 5703+
86dc4139 5704+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 5705+ h_dir = d_inode(h_parent);
86dc4139 5706+ IMustLock(h_dir);
523b37e3
AM
5707+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry);
5708+ /* no delegation since it is just created */
f2c43d5f
AM
5709+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL,
5710+ /*flags*/0);
86dc4139
AM
5711+ dput(h_path->dentry);
5712+
5713+out:
5714+ return err;
5715+}
5716+
1facf9fc 5717+/*
5718+ * copyup the @dentry from @bsrc to @bdst.
5719+ * the caller must set the both of lower dentries.
5720+ * @len is for truncating when it is -1 copyup the entire file.
5721+ * in link/rename cases, @dst_parent may be different from the real one.
c2b27bf2 5722+ * basic->bsrc can be larger than basic->bdst.
f2c43d5f 5723+ * aufs doesn't touch the credential so
acd2b654 5724+ * security_inode_copy_up{,_xattr}() are unnecessary.
1facf9fc 5725+ */
c2b27bf2 5726+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5727+{
5728+ int err, rerr;
5afbbe0d 5729+ aufs_bindex_t old_ibtop;
1facf9fc 5730+ unsigned char isdir, plink;
1facf9fc 5731+ struct dentry *h_src, *h_dst, *h_parent;
5527c038 5732+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode;
1facf9fc 5733+ struct super_block *sb;
86dc4139 5734+ struct au_branch *br;
acd2b654 5735+ /* to reduce stack size */
c2b27bf2
AM
5736+ struct {
5737+ struct au_dtime dt;
5738+ struct path h_path;
5739+ struct au_cpup_reg_attr h_src_attr;
5740+ } *a;
1facf9fc 5741+
c2b27bf2
AM
5742+ err = -ENOMEM;
5743+ a = kmalloc(sizeof(*a), GFP_NOFS);
5744+ if (unlikely(!a))
5745+ goto out;
5746+ a->h_src_attr.valid = 0;
1facf9fc 5747+
c2b27bf2
AM
5748+ sb = cpg->dentry->d_sb;
5749+ br = au_sbr(sb, cpg->bdst);
5750+ a->h_path.mnt = au_br_mnt(br);
5751+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
1facf9fc 5752+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5753+ h_dir = d_inode(h_parent);
1facf9fc 5754+ IMustLock(h_dir);
5755+
c2b27bf2 5756+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5757+ inode = d_inode(cpg->dentry);
1facf9fc 5758+
5759+ if (!dst_parent)
c2b27bf2 5760+ dst_parent = dget_parent(cpg->dentry);
1facf9fc 5761+ else
5762+ dget(dst_parent);
5763+
5764+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
c2b27bf2 5765+ dst_inode = au_h_iptr(inode, cpg->bdst);
1facf9fc 5766+ if (dst_inode) {
5767+ if (unlikely(!plink)) {
5768+ err = -EIO;
027c5e7a
AM
5769+ AuIOErr("hi%lu(i%lu) exists on b%d "
5770+ "but plink is disabled\n",
c2b27bf2
AM
5771+ dst_inode->i_ino, inode->i_ino, cpg->bdst);
5772+ goto out_parent;
1facf9fc 5773+ }
5774+
5775+ if (dst_inode->i_nlink) {
c2b27bf2 5776+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5777+
c2b27bf2 5778+ h_src = au_plink_lkup(inode, cpg->bdst);
1facf9fc 5779+ err = PTR_ERR(h_src);
5780+ if (IS_ERR(h_src))
c2b27bf2 5781+ goto out_parent;
5527c038 5782+ if (unlikely(d_is_negative(h_src))) {
1facf9fc 5783+ err = -EIO;
79b8bda9 5784+ AuIOErr("i%lu exists on b%d "
027c5e7a 5785+ "but not pseudo-linked\n",
79b8bda9 5786+ inode->i_ino, cpg->bdst);
1facf9fc 5787+ dput(h_src);
c2b27bf2 5788+ goto out_parent;
1facf9fc 5789+ }
5790+
5791+ if (do_dt) {
c2b27bf2
AM
5792+ a->h_path.dentry = h_parent;
5793+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
1facf9fc 5794+ }
86dc4139 5795+
c2b27bf2 5796+ a->h_path.dentry = h_dst;
523b37e3
AM
5797+ delegated = NULL;
5798+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated);
c2b27bf2 5799+ if (!err && au_ftest_cpup(cpg->flags, RENAME))
392086de 5800+ err = au_do_ren_after_cpup(cpg, &a->h_path);
1facf9fc 5801+ if (do_dt)
c2b27bf2 5802+ au_dtime_revert(&a->dt);
523b37e3
AM
5803+ if (unlikely(err == -EWOULDBLOCK)) {
5804+ pr_warn("cannot retry for NFSv4 delegation"
5805+ " for an internal link\n");
5806+ iput(delegated);
5807+ }
1facf9fc 5808+ dput(h_src);
c2b27bf2 5809+ goto out_parent;
1facf9fc 5810+ } else
5811+ /* todo: cpup_wh_file? */
5812+ /* udba work */
4a4d8108 5813+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 5814+ }
5815+
86dc4139 5816+ isdir = S_ISDIR(inode->i_mode);
5afbbe0d 5817+ old_ibtop = au_ibtop(inode);
c2b27bf2 5818+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr);
1facf9fc 5819+ if (unlikely(err))
86dc4139 5820+ goto out_rev;
5527c038 5821+ dst_inode = d_inode(h_dst);
febd17d6 5822+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2);
86dc4139 5823+ /* todo: necessary? */
c2b27bf2 5824+ /* au_pin_hdir_unlock(cpg->pin); */
1facf9fc 5825+
c2b27bf2 5826+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr);
86dc4139
AM
5827+ if (unlikely(err)) {
5828+ /* todo: necessary? */
c2b27bf2 5829+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */
febd17d6 5830+ inode_unlock(dst_inode);
86dc4139
AM
5831+ goto out_rev;
5832+ }
5833+
5afbbe0d 5834+ if (cpg->bdst < old_ibtop) {
86dc4139 5835+ if (S_ISREG(inode->i_mode)) {
c2b27bf2 5836+ err = au_dy_iaop(inode, cpg->bdst, dst_inode);
86dc4139 5837+ if (unlikely(err)) {
c2b27bf2
AM
5838+ /* ignore an error */
5839+ /* au_pin_hdir_relock(cpg->pin); */
febd17d6 5840+ inode_unlock(dst_inode);
86dc4139 5841+ goto out_rev;
4a4d8108 5842+ }
4a4d8108 5843+ }
5afbbe0d 5844+ au_set_ibtop(inode, cpg->bdst);
c2b27bf2 5845+ } else
5afbbe0d 5846+ au_set_ibbot(inode, cpg->bdst);
c2b27bf2 5847+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode),
86dc4139
AM
5848+ au_hi_flags(inode, isdir));
5849+
5850+ /* todo: necessary? */
c2b27bf2 5851+ /* err = au_pin_hdir_relock(cpg->pin); */
febd17d6 5852+ inode_unlock(dst_inode);
86dc4139
AM
5853+ if (unlikely(err))
5854+ goto out_rev;
5855+
5527c038 5856+ src_inode = d_inode(h_src);
86dc4139 5857+ if (!isdir
5527c038
JR
5858+ && (src_inode->i_nlink > 1
5859+ || src_inode->i_state & I_LINKABLE)
86dc4139 5860+ && plink)
c2b27bf2 5861+ au_plink_append(inode, cpg->bdst, h_dst);
86dc4139 5862+
c2b27bf2
AM
5863+ if (au_ftest_cpup(cpg->flags, RENAME)) {
5864+ a->h_path.dentry = h_dst;
392086de 5865+ err = au_do_ren_after_cpup(cpg, &a->h_path);
86dc4139
AM
5866+ }
5867+ if (!err)
c2b27bf2 5868+ goto out_parent; /* success */
1facf9fc 5869+
5870+ /* revert */
4a4d8108 5871+out_rev:
c2b27bf2
AM
5872+ a->h_path.dentry = h_parent;
5873+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
5874+ a->h_path.dentry = h_dst;
86dc4139 5875+ rerr = 0;
5527c038 5876+ if (d_is_positive(h_dst)) {
523b37e3
AM
5877+ if (!isdir) {
5878+ /* no delegation since it is just created */
5879+ rerr = vfsub_unlink(h_dir, &a->h_path,
5880+ /*delegated*/NULL, /*force*/0);
5881+ } else
c2b27bf2 5882+ rerr = vfsub_rmdir(h_dir, &a->h_path);
86dc4139 5883+ }
c2b27bf2 5884+ au_dtime_revert(&a->dt);
1facf9fc 5885+ if (rerr) {
5886+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
5887+ err = -EIO;
5888+ }
c2b27bf2 5889+out_parent:
1facf9fc 5890+ dput(dst_parent);
9f237c51 5891+ au_kfree_rcu(a);
c2b27bf2 5892+out:
1facf9fc 5893+ return err;
5894+}
5895+
7e9cd9fe 5896+#if 0 /* reserved */
1facf9fc 5897+struct au_cpup_single_args {
5898+ int *errp;
c2b27bf2 5899+ struct au_cp_generic *cpg;
1facf9fc 5900+ struct dentry *dst_parent;
5901+};
5902+
5903+static void au_call_cpup_single(void *args)
5904+{
5905+ struct au_cpup_single_args *a = args;
86dc4139 5906+
c2b27bf2
AM
5907+ au_pin_hdir_acquire_nest(a->cpg->pin);
5908+ *a->errp = au_cpup_single(a->cpg, a->dst_parent);
5909+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5910+}
c2b27bf2 5911+#endif
1facf9fc 5912+
53392da6
AM
5913+/*
5914+ * prevent SIGXFSZ in copy-up.
5915+ * testing CAP_MKNOD is for generic fs,
5916+ * but CAP_FSETID is for xfs only, currently.
5917+ */
86dc4139 5918+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode)
53392da6
AM
5919+{
5920+ int do_sio;
86dc4139
AM
5921+ struct super_block *sb;
5922+ struct inode *h_dir;
53392da6
AM
5923+
5924+ do_sio = 0;
86dc4139 5925+ sb = au_pinned_parent(pin)->d_sb;
53392da6
AM
5926+ if (!au_wkq_test()
5927+ && (!au_sbi(sb)->si_plink_maint_pid
5928+ || au_plink_maint(sb, AuLock_NOPLM))) {
5929+ switch (mode & S_IFMT) {
5930+ case S_IFREG:
5931+ /* no condition about RLIMIT_FSIZE and the file size */
5932+ do_sio = 1;
5933+ break;
5934+ case S_IFCHR:
5935+ case S_IFBLK:
5936+ do_sio = !capable(CAP_MKNOD);
5937+ break;
5938+ }
5939+ if (!do_sio)
5940+ do_sio = ((mode & (S_ISUID | S_ISGID))
5941+ && !capable(CAP_FSETID));
86dc4139
AM
5942+ /* this workaround may be removed in the future */
5943+ if (!do_sio) {
5944+ h_dir = au_pinned_h_dir(pin);
5945+ do_sio = h_dir->i_mode & S_ISVTX;
5946+ }
53392da6
AM
5947+ }
5948+
5949+ return do_sio;
5950+}
5951+
7e9cd9fe 5952+#if 0 /* reserved */
c2b27bf2 5953+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5954+{
5955+ int err, wkq_err;
1facf9fc 5956+ struct dentry *h_dentry;
5957+
c2b27bf2 5958+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5959+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode))
c2b27bf2 5960+ err = au_cpup_single(cpg, dst_parent);
1facf9fc 5961+ else {
5962+ struct au_cpup_single_args args = {
5963+ .errp = &err,
c2b27bf2
AM
5964+ .cpg = cpg,
5965+ .dst_parent = dst_parent
1facf9fc 5966+ };
5967+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
5968+ if (unlikely(wkq_err))
5969+ err = wkq_err;
5970+ }
5971+
5972+ return err;
5973+}
c2b27bf2 5974+#endif
1facf9fc 5975+
5976+/*
5977+ * copyup the @dentry from the first active lower branch to @bdst,
5978+ * using au_cpup_single().
5979+ */
c2b27bf2 5980+static int au_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5981+{
5982+ int err;
c2b27bf2
AM
5983+ unsigned int flags_orig;
5984+ struct dentry *dentry;
5985+
5986+ AuDebugOn(cpg->bsrc < 0);
1facf9fc 5987+
c2b27bf2 5988+ dentry = cpg->dentry;
86dc4139 5989+ DiMustWriteLock(dentry);
1facf9fc 5990+
c2b27bf2 5991+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1);
1facf9fc 5992+ if (!err) {
c2b27bf2
AM
5993+ flags_orig = cpg->flags;
5994+ au_fset_cpup(cpg->flags, RENAME);
5995+ err = au_cpup_single(cpg, NULL);
5996+ cpg->flags = flags_orig;
1facf9fc 5997+ if (!err)
5998+ return 0; /* success */
5999+
6000+ /* revert */
c2b27bf2 6001+ au_set_h_dptr(dentry, cpg->bdst, NULL);
5afbbe0d 6002+ au_set_dbtop(dentry, cpg->bsrc);
1facf9fc 6003+ }
6004+
6005+ return err;
6006+}
6007+
6008+struct au_cpup_simple_args {
6009+ int *errp;
c2b27bf2 6010+ struct au_cp_generic *cpg;
1facf9fc 6011+};
6012+
6013+static void au_call_cpup_simple(void *args)
6014+{
6015+ struct au_cpup_simple_args *a = args;
86dc4139 6016+
c2b27bf2
AM
6017+ au_pin_hdir_acquire_nest(a->cpg->pin);
6018+ *a->errp = au_cpup_simple(a->cpg);
6019+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 6020+}
6021+
c2b27bf2 6022+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 6023+{
6024+ int err, wkq_err;
c2b27bf2
AM
6025+ struct dentry *dentry, *parent;
6026+ struct file *h_file;
1facf9fc 6027+ struct inode *h_dir;
6028+
c2b27bf2
AM
6029+ dentry = cpg->dentry;
6030+ h_file = NULL;
6031+ if (au_ftest_cpup(cpg->flags, HOPEN)) {
6032+ AuDebugOn(cpg->bsrc < 0);
392086de 6033+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0);
c2b27bf2
AM
6034+ err = PTR_ERR(h_file);
6035+ if (IS_ERR(h_file))
6036+ goto out;
6037+ }
6038+
1facf9fc 6039+ parent = dget_parent(dentry);
5527c038 6040+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
53392da6 6041+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
5527c038 6042+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 6043+ err = au_cpup_simple(cpg);
1facf9fc 6044+ else {
6045+ struct au_cpup_simple_args args = {
6046+ .errp = &err,
c2b27bf2 6047+ .cpg = cpg
1facf9fc 6048+ };
6049+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
6050+ if (unlikely(wkq_err))
6051+ err = wkq_err;
6052+ }
6053+
6054+ dput(parent);
c2b27bf2
AM
6055+ if (h_file)
6056+ au_h_open_post(dentry, cpg->bsrc, h_file);
6057+
6058+out:
1facf9fc 6059+ return err;
6060+}
6061+
c2b27bf2 6062+int au_sio_cpup_simple(struct au_cp_generic *cpg)
367653fa 6063+{
5afbbe0d 6064+ aufs_bindex_t bsrc, bbot;
c2b27bf2 6065+ struct dentry *dentry, *h_dentry;
367653fa 6066+
c2b27bf2
AM
6067+ if (cpg->bsrc < 0) {
6068+ dentry = cpg->dentry;
5afbbe0d
AM
6069+ bbot = au_dbbot(dentry);
6070+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) {
c2b27bf2
AM
6071+ h_dentry = au_h_dptr(dentry, bsrc);
6072+ if (h_dentry) {
5527c038 6073+ AuDebugOn(d_is_negative(h_dentry));
c2b27bf2
AM
6074+ break;
6075+ }
6076+ }
5afbbe0d 6077+ AuDebugOn(bsrc > bbot);
c2b27bf2 6078+ cpg->bsrc = bsrc;
367653fa 6079+ }
c2b27bf2
AM
6080+ AuDebugOn(cpg->bsrc <= cpg->bdst);
6081+ return au_do_sio_cpup_simple(cpg);
6082+}
367653fa 6083+
c2b27bf2
AM
6084+int au_sio_cpdown_simple(struct au_cp_generic *cpg)
6085+{
6086+ AuDebugOn(cpg->bdst <= cpg->bsrc);
6087+ return au_do_sio_cpup_simple(cpg);
367653fa
AM
6088+}
6089+
1facf9fc 6090+/* ---------------------------------------------------------------------- */
6091+
6092+/*
6093+ * copyup the deleted file for writing.
6094+ */
c2b27bf2
AM
6095+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry,
6096+ struct file *file)
1facf9fc 6097+{
6098+ int err;
c2b27bf2
AM
6099+ unsigned int flags_orig;
6100+ aufs_bindex_t bsrc_orig;
c2b27bf2 6101+ struct au_dinfo *dinfo;
5afbbe0d
AM
6102+ struct {
6103+ struct au_hdentry *hd;
6104+ struct dentry *h_dentry;
6105+ } hdst, hsrc;
1facf9fc 6106+
c2b27bf2 6107+ dinfo = au_di(cpg->dentry);
1308ab2a 6108+ AuRwMustWriteLock(&dinfo->di_rwsem);
6109+
c2b27bf2 6110+ bsrc_orig = cpg->bsrc;
5afbbe0d
AM
6111+ cpg->bsrc = dinfo->di_btop;
6112+ hdst.hd = au_hdentry(dinfo, cpg->bdst);
6113+ hdst.h_dentry = hdst.hd->hd_dentry;
6114+ hdst.hd->hd_dentry = wh_dentry;
6115+ dinfo->di_btop = cpg->bdst;
6116+
6117+ hsrc.h_dentry = NULL;
027c5e7a 6118+ if (file) {
5afbbe0d
AM
6119+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc);
6120+ hsrc.h_dentry = hsrc.hd->hd_dentry;
6121+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry;
027c5e7a 6122+ }
c2b27bf2
AM
6123+ flags_orig = cpg->flags;
6124+ cpg->flags = !AuCpup_DTIME;
6125+ err = au_cpup_single(cpg, /*h_parent*/NULL);
6126+ cpg->flags = flags_orig;
027c5e7a
AM
6127+ if (file) {
6128+ if (!err)
6129+ err = au_reopen_nondir(file);
5afbbe0d 6130+ hsrc.hd->hd_dentry = hsrc.h_dentry;
1facf9fc 6131+ }
5afbbe0d
AM
6132+ hdst.hd->hd_dentry = hdst.h_dentry;
6133+ dinfo->di_btop = cpg->bsrc;
c2b27bf2 6134+ cpg->bsrc = bsrc_orig;
1facf9fc 6135+
6136+ return err;
6137+}
6138+
c2b27bf2 6139+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6140+{
6141+ int err;
c2b27bf2 6142+ aufs_bindex_t bdst;
1facf9fc 6143+ struct au_dtime dt;
c2b27bf2 6144+ struct dentry *dentry, *parent, *h_parent, *wh_dentry;
1facf9fc 6145+ struct au_branch *br;
6146+ struct path h_path;
6147+
c2b27bf2
AM
6148+ dentry = cpg->dentry;
6149+ bdst = cpg->bdst;
1facf9fc 6150+ br = au_sbr(dentry->d_sb, bdst);
6151+ parent = dget_parent(dentry);
6152+ h_parent = au_h_dptr(parent, bdst);
6153+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
6154+ err = PTR_ERR(wh_dentry);
6155+ if (IS_ERR(wh_dentry))
6156+ goto out;
6157+
6158+ h_path.dentry = h_parent;
86dc4139 6159+ h_path.mnt = au_br_mnt(br);
1facf9fc 6160+ au_dtime_store(&dt, parent, &h_path);
c2b27bf2 6161+ err = au_do_cpup_wh(cpg, wh_dentry, file);
1facf9fc 6162+ if (unlikely(err))
6163+ goto out_wh;
6164+
6165+ dget(wh_dentry);
6166+ h_path.dentry = wh_dentry;
2000de60 6167+ if (!d_is_dir(wh_dentry)) {
523b37e3 6168+ /* no delegation since it is just created */
5527c038 6169+ err = vfsub_unlink(d_inode(h_parent), &h_path,
523b37e3
AM
6170+ /*delegated*/NULL, /*force*/0);
6171+ } else
5527c038 6172+ err = vfsub_rmdir(d_inode(h_parent), &h_path);
1facf9fc 6173+ if (unlikely(err)) {
523b37e3
AM
6174+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n",
6175+ wh_dentry, err);
1facf9fc 6176+ err = -EIO;
6177+ }
6178+ au_dtime_revert(&dt);
5527c038 6179+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry);
1facf9fc 6180+
4f0767ce 6181+out_wh:
1facf9fc 6182+ dput(wh_dentry);
4f0767ce 6183+out:
1facf9fc 6184+ dput(parent);
6185+ return err;
6186+}
6187+
6188+struct au_cpup_wh_args {
6189+ int *errp;
c2b27bf2 6190+ struct au_cp_generic *cpg;
1facf9fc 6191+ struct file *file;
6192+};
6193+
6194+static void au_call_cpup_wh(void *args)
6195+{
6196+ struct au_cpup_wh_args *a = args;
86dc4139 6197+
c2b27bf2
AM
6198+ au_pin_hdir_acquire_nest(a->cpg->pin);
6199+ *a->errp = au_cpup_wh(a->cpg, a->file);
6200+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 6201+}
6202+
c2b27bf2 6203+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6204+{
6205+ int err, wkq_err;
c2b27bf2 6206+ aufs_bindex_t bdst;
c1595e42 6207+ struct dentry *dentry, *parent, *h_orph, *h_parent;
86dc4139 6208+ struct inode *dir, *h_dir, *h_tmpdir;
1facf9fc 6209+ struct au_wbr *wbr;
c2b27bf2 6210+ struct au_pin wh_pin, *pin_orig;
1facf9fc 6211+
c2b27bf2
AM
6212+ dentry = cpg->dentry;
6213+ bdst = cpg->bdst;
1facf9fc 6214+ parent = dget_parent(dentry);
5527c038 6215+ dir = d_inode(parent);
1facf9fc 6216+ h_orph = NULL;
6217+ h_parent = NULL;
6218+ h_dir = au_igrab(au_h_iptr(dir, bdst));
6219+ h_tmpdir = h_dir;
c2b27bf2 6220+ pin_orig = NULL;
1facf9fc 6221+ if (!h_dir->i_nlink) {
6222+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
6223+ h_orph = wbr->wbr_orph;
6224+
6225+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 6226+ au_set_h_dptr(parent, bdst, dget(h_orph));
5527c038 6227+ h_tmpdir = d_inode(h_orph);
1facf9fc 6228+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
6229+
febd17d6 6230+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3);
4a4d8108 6231+ /* todo: au_h_open_pre()? */
86dc4139 6232+
c2b27bf2 6233+ pin_orig = cpg->pin;
86dc4139 6234+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
c2b27bf2
AM
6235+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED);
6236+ cpg->pin = &wh_pin;
1facf9fc 6237+ }
6238+
53392da6 6239+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
5527c038 6240+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 6241+ err = au_cpup_wh(cpg, file);
1facf9fc 6242+ else {
6243+ struct au_cpup_wh_args args = {
6244+ .errp = &err,
c2b27bf2
AM
6245+ .cpg = cpg,
6246+ .file = file
1facf9fc 6247+ };
6248+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
6249+ if (unlikely(wkq_err))
6250+ err = wkq_err;
6251+ }
6252+
6253+ if (h_orph) {
febd17d6 6254+ inode_unlock(h_tmpdir);
4a4d8108 6255+ /* todo: au_h_open_post()? */
1facf9fc 6256+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 6257+ au_set_h_dptr(parent, bdst, h_parent);
c2b27bf2
AM
6258+ AuDebugOn(!pin_orig);
6259+ cpg->pin = pin_orig;
1facf9fc 6260+ }
6261+ iput(h_dir);
6262+ dput(parent);
6263+
6264+ return err;
6265+}
6266+
6267+/* ---------------------------------------------------------------------- */
6268+
6269+/*
6270+ * generic routine for both of copy-up and copy-down.
6271+ */
6272+/* cf. revalidate function in file.c */
6273+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6274+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6275+ struct au_pin *pin,
1facf9fc 6276+ struct dentry *h_parent, void *arg),
6277+ void *arg)
6278+{
6279+ int err;
6280+ struct au_pin pin;
5527c038 6281+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry;
1facf9fc 6282+
6283+ err = 0;
6284+ parent = dget_parent(dentry);
6285+ if (IS_ROOT(parent))
6286+ goto out;
6287+
6288+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
6289+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
6290+
6291+ /* do not use au_dpage */
6292+ real_parent = parent;
6293+ while (1) {
6294+ dput(parent);
6295+ parent = dget_parent(dentry);
6296+ h_parent = au_h_dptr(parent, bdst);
6297+ if (h_parent)
6298+ goto out; /* success */
6299+
6300+ /* find top dir which is necessary to cpup */
6301+ do {
6302+ d = parent;
6303+ dput(parent);
6304+ parent = dget_parent(d);
6305+ di_read_lock_parent3(parent, !AuLock_IR);
6306+ h_parent = au_h_dptr(parent, bdst);
6307+ di_read_unlock(parent, !AuLock_IR);
6308+ } while (!h_parent);
6309+
6310+ if (d != real_parent)
6311+ di_write_lock_child3(d);
6312+
6313+ /* somebody else might create while we were sleeping */
5527c038
JR
6314+ h_dentry = au_h_dptr(d, bdst);
6315+ if (!h_dentry || d_is_negative(h_dentry)) {
6316+ if (h_dentry)
5afbbe0d 6317+ au_update_dbtop(d);
1facf9fc 6318+
6319+ au_pin_set_dentry(&pin, d);
6320+ err = au_do_pin(&pin);
6321+ if (!err) {
86dc4139 6322+ err = cp(d, bdst, &pin, h_parent, arg);
1facf9fc 6323+ au_unpin(&pin);
6324+ }
6325+ }
6326+
6327+ if (d != real_parent)
6328+ di_write_unlock(d);
6329+ if (unlikely(err))
6330+ break;
6331+ }
6332+
4f0767ce 6333+out:
1facf9fc 6334+ dput(parent);
6335+ return err;
6336+}
6337+
6338+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6339+ struct au_pin *pin,
2000de60 6340+ struct dentry *h_parent __maybe_unused,
1facf9fc 6341+ void *arg __maybe_unused)
6342+{
c2b27bf2
AM
6343+ struct au_cp_generic cpg = {
6344+ .dentry = dentry,
6345+ .bdst = bdst,
6346+ .bsrc = -1,
6347+ .len = 0,
6348+ .pin = pin,
6349+ .flags = AuCpup_DTIME
6350+ };
6351+ return au_sio_cpup_simple(&cpg);
1facf9fc 6352+}
6353+
6354+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6355+{
6356+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
6357+}
6358+
6359+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6360+{
6361+ int err;
6362+ struct dentry *parent;
6363+ struct inode *dir;
6364+
6365+ parent = dget_parent(dentry);
5527c038 6366+ dir = d_inode(parent);
1facf9fc 6367+ err = 0;
6368+ if (au_h_iptr(dir, bdst))
6369+ goto out;
6370+
6371+ di_read_unlock(parent, AuLock_IR);
6372+ di_write_lock_parent(parent);
6373+ /* someone else might change our inode while we were sleeping */
6374+ if (!au_h_iptr(dir, bdst))
6375+ err = au_cpup_dirs(dentry, bdst);
6376+ di_downgrade_lock(parent, AuLock_IR);
6377+
4f0767ce 6378+out:
1facf9fc 6379+ dput(parent);
6380+ return err;
6381+}
7f207e10 6382diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
eca34b5c
AM
6383--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
6384+++ linux/fs/aufs/cpup.h 2019-07-11 15:42:14.462237786 +0200
062440b3
AM
6385@@ -0,0 +1,100 @@
6386+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 6387+/*
ba1aed25 6388+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 6389+ *
6390+ * This program, aufs is free software; you can redistribute it and/or modify
6391+ * it under the terms of the GNU General Public License as published by
6392+ * the Free Software Foundation; either version 2 of the License, or
6393+ * (at your option) any later version.
dece6358
AM
6394+ *
6395+ * This program is distributed in the hope that it will be useful,
6396+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6397+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6398+ * GNU General Public License for more details.
6399+ *
6400+ * You should have received a copy of the GNU General Public License
523b37e3 6401+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6402+ */
6403+
6404+/*
6405+ * copy-up/down functions
6406+ */
6407+
6408+#ifndef __AUFS_CPUP_H__
6409+#define __AUFS_CPUP_H__
6410+
6411+#ifdef __KERNEL__
6412+
dece6358 6413+#include <linux/path.h>
1facf9fc 6414+
dece6358
AM
6415+struct inode;
6416+struct file;
86dc4139 6417+struct au_pin;
dece6358 6418+
86dc4139 6419+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags);
1facf9fc 6420+void au_cpup_attr_timesizes(struct inode *inode);
6421+void au_cpup_attr_nlink(struct inode *inode, int force);
6422+void au_cpup_attr_changeable(struct inode *inode);
6423+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
6424+void au_cpup_attr_all(struct inode *inode, int force);
6425+
6426+/* ---------------------------------------------------------------------- */
6427+
c2b27bf2
AM
6428+struct au_cp_generic {
6429+ struct dentry *dentry;
6430+ aufs_bindex_t bdst, bsrc;
6431+ loff_t len;
6432+ struct au_pin *pin;
6433+ unsigned int flags;
6434+};
6435+
1facf9fc 6436+/* cpup flags */
392086de
AM
6437+#define AuCpup_DTIME 1 /* do dtime_store/revert */
6438+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
6439+ for link(2) */
6440+#define AuCpup_RENAME (1 << 2) /* rename after cpup */
6441+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in
6442+ cpup */
6443+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the
6444+ existing entry */
6445+#define AuCpup_RWDST (1 << 5) /* force write target even if
6446+ the branch is marked as RO */
c2b27bf2 6447+
8b6a4947
AM
6448+#ifndef CONFIG_AUFS_BR_HFSPLUS
6449+#undef AuCpup_HOPEN
6450+#define AuCpup_HOPEN 0
6451+#endif
6452+
1facf9fc 6453+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
6454+#define au_fset_cpup(flags, name) \
6455+ do { (flags) |= AuCpup_##name; } while (0)
6456+#define au_fclr_cpup(flags, name) \
6457+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 6458+
6459+int au_copy_file(struct file *dst, struct file *src, loff_t len);
c2b27bf2
AM
6460+int au_sio_cpup_simple(struct au_cp_generic *cpg);
6461+int au_sio_cpdown_simple(struct au_cp_generic *cpg);
6462+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file);
1facf9fc 6463+
6464+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6465+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6466+ struct au_pin *pin,
1facf9fc 6467+ struct dentry *h_parent, void *arg),
6468+ void *arg);
6469+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6470+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6471+
6472+/* ---------------------------------------------------------------------- */
6473+
6474+/* keep timestamps when copyup */
6475+struct au_dtime {
6476+ struct dentry *dt_dentry;
6477+ struct path dt_h_path;
cd7a4cd9 6478+ struct timespec64 dt_atime, dt_mtime;
1facf9fc 6479+};
6480+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
6481+ struct path *h_path);
6482+void au_dtime_revert(struct au_dtime *dt);
6483+
6484+#endif /* __KERNEL__ */
6485+#endif /* __AUFS_CPUP_H__ */
7f207e10 6486diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
eca34b5c
AM
6487--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
6488+++ linux/fs/aufs/dbgaufs.c 2019-07-11 15:42:14.462237786 +0200
9f237c51 6489@@ -0,0 +1,526 @@
cd7a4cd9 6490+// SPDX-License-Identifier: GPL-2.0
1facf9fc 6491+/*
ba1aed25 6492+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 6493+ *
6494+ * This program, aufs is free software; you can redistribute it and/or modify
6495+ * it under the terms of the GNU General Public License as published by
6496+ * the Free Software Foundation; either version 2 of the License, or
6497+ * (at your option) any later version.
dece6358
AM
6498+ *
6499+ * This program is distributed in the hope that it will be useful,
6500+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6501+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6502+ * GNU General Public License for more details.
6503+ *
6504+ * You should have received a copy of the GNU General Public License
523b37e3 6505+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6506+ */
6507+
6508+/*
6509+ * debugfs interface
6510+ */
6511+
6512+#include <linux/debugfs.h>
6513+#include "aufs.h"
6514+
6515+#ifndef CONFIG_SYSFS
6516+#error DEBUG_FS depends upon SYSFS
6517+#endif
6518+
6519+static struct dentry *dbgaufs;
cd7a4cd9 6520+static const mode_t dbgaufs_mode = 0444;
1facf9fc 6521+
6522+/* 20 is max digits length of ulong 64 */
6523+struct dbgaufs_arg {
6524+ int n;
6525+ char a[20 * 4];
6526+};
6527+
6528+/*
6529+ * common function for all XINO files
6530+ */
6531+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
6532+ struct file *file)
6533+{
9f237c51
AM
6534+ void *p;
6535+
6536+ p = file->private_data;
6537+ if (p) {
6538+ /* this is struct dbgaufs_arg */
6539+ AuDebugOn(!au_kfree_sz_test(p));
6540+ au_kfree_do_rcu(p);
6541+ }
1facf9fc 6542+ return 0;
6543+}
6544+
062440b3
AM
6545+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt,
6546+ int cnt)
1facf9fc 6547+{
6548+ int err;
6549+ struct kstat st;
6550+ struct dbgaufs_arg *p;
6551+
6552+ err = -ENOMEM;
6553+ p = kmalloc(sizeof(*p), GFP_NOFS);
6554+ if (unlikely(!p))
6555+ goto out;
6556+
6557+ err = 0;
6558+ p->n = 0;
6559+ file->private_data = p;
6560+ if (!xf)
6561+ goto out;
6562+
521ced18 6563+ err = vfsub_getattr(&xf->f_path, &st);
1facf9fc 6564+ if (!err) {
6565+ if (do_fcnt)
6566+ p->n = snprintf
062440b3
AM
6567+ (p->a, sizeof(p->a), "%d, %llux%u %lld\n",
6568+ cnt, st.blocks, st.blksize,
1facf9fc 6569+ (long long)st.size);
6570+ else
521ced18 6571+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n",
1facf9fc 6572+ st.blocks, st.blksize,
6573+ (long long)st.size);
6574+ AuDebugOn(p->n >= sizeof(p->a));
6575+ } else {
6576+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
6577+ err = 0;
6578+ }
6579+
4f0767ce 6580+out:
1facf9fc 6581+ return err;
1facf9fc 6582+}
6583+
6584+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
6585+ size_t count, loff_t *ppos)
6586+{
6587+ struct dbgaufs_arg *p;
6588+
6589+ p = file->private_data;
6590+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6591+}
6592+
6593+/* ---------------------------------------------------------------------- */
6594+
86dc4139
AM
6595+struct dbgaufs_plink_arg {
6596+ int n;
6597+ char a[];
6598+};
6599+
6600+static int dbgaufs_plink_release(struct inode *inode __maybe_unused,
6601+ struct file *file)
6602+{
1c60b727 6603+ free_page((unsigned long)file->private_data);
86dc4139
AM
6604+ return 0;
6605+}
6606+
6607+static int dbgaufs_plink_open(struct inode *inode, struct file *file)
6608+{
6609+ int err, i, limit;
6610+ unsigned long n, sum;
6611+ struct dbgaufs_plink_arg *p;
6612+ struct au_sbinfo *sbinfo;
6613+ struct super_block *sb;
8b6a4947 6614+ struct hlist_bl_head *hbl;
86dc4139
AM
6615+
6616+ err = -ENOMEM;
6617+ p = (void *)get_zeroed_page(GFP_NOFS);
6618+ if (unlikely(!p))
6619+ goto out;
6620+
6621+ err = -EFBIG;
6622+ sbinfo = inode->i_private;
6623+ sb = sbinfo->si_sb;
6624+ si_noflush_read_lock(sb);
6625+ if (au_opt_test(au_mntflags(sb), PLINK)) {
6626+ limit = PAGE_SIZE - sizeof(p->n);
6627+
6628+ /* the number of buckets */
6629+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH);
6630+ p->n += n;
6631+ limit -= n;
6632+
6633+ sum = 0;
8b6a4947
AM
6634+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH;
6635+ i++, hbl++) {
6636+ n = au_hbl_count(hbl);
86dc4139
AM
6637+ sum += n;
6638+
6639+ n = snprintf(p->a + p->n, limit, "%lu ", n);
6640+ p->n += n;
6641+ limit -= n;
6642+ if (unlikely(limit <= 0))
6643+ goto out_free;
6644+ }
6645+ p->a[p->n - 1] = '\n';
6646+
6647+ /* the sum of plinks */
6648+ n = snprintf(p->a + p->n, limit, "%lu\n", sum);
6649+ p->n += n;
6650+ limit -= n;
6651+ if (unlikely(limit <= 0))
6652+ goto out_free;
6653+ } else {
6654+#define str "1\n0\n0\n"
6655+ p->n = sizeof(str) - 1;
6656+ strcpy(p->a, str);
6657+#undef str
6658+ }
6659+ si_read_unlock(sb);
6660+
6661+ err = 0;
6662+ file->private_data = p;
6663+ goto out; /* success */
6664+
6665+out_free:
1c60b727 6666+ free_page((unsigned long)p);
86dc4139
AM
6667+out:
6668+ return err;
6669+}
6670+
6671+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf,
6672+ size_t count, loff_t *ppos)
6673+{
6674+ struct dbgaufs_plink_arg *p;
6675+
6676+ p = file->private_data;
6677+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6678+}
6679+
6680+static const struct file_operations dbgaufs_plink_fop = {
6681+ .owner = THIS_MODULE,
6682+ .open = dbgaufs_plink_open,
6683+ .release = dbgaufs_plink_release,
6684+ .read = dbgaufs_plink_read
6685+};
6686+
6687+/* ---------------------------------------------------------------------- */
6688+
1facf9fc 6689+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
6690+{
6691+ int err;
6692+ struct au_sbinfo *sbinfo;
6693+ struct super_block *sb;
6694+
6695+ sbinfo = inode->i_private;
6696+ sb = sbinfo->si_sb;
6697+ si_noflush_read_lock(sb);
062440b3 6698+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6699+ si_read_unlock(sb);
6700+ return err;
6701+}
6702+
6703+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 6704+ .owner = THIS_MODULE,
1facf9fc 6705+ .open = dbgaufs_xib_open,
6706+ .release = dbgaufs_xi_release,
6707+ .read = dbgaufs_xi_read
6708+};
6709+
6710+/* ---------------------------------------------------------------------- */
6711+
6712+#define DbgaufsXi_PREFIX "xi"
6713+
6714+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
6715+{
acd2b654 6716+ int err, idx;
1facf9fc 6717+ long l;
acd2b654
AM
6718+ aufs_bindex_t bindex;
6719+ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8];
1facf9fc 6720+ struct au_sbinfo *sbinfo;
6721+ struct super_block *sb;
acd2b654 6722+ struct au_xino *xi;
1facf9fc 6723+ struct file *xf;
6724+ struct qstr *name;
062440b3 6725+ struct au_branch *br;
1facf9fc 6726+
6727+ err = -ENOENT;
2000de60 6728+ name = &file->f_path.dentry->d_name;
1facf9fc 6729+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
6730+ || memcmp(name->name, DbgaufsXi_PREFIX,
6731+ sizeof(DbgaufsXi_PREFIX) - 1)))
6732+ goto out;
acd2b654
AM
6733+
6734+ AuDebugOn(name->len >= sizeof(a));
6735+ memcpy(a, name->name, name->len);
6736+ a[name->len] = '\0';
6737+ p = strchr(a, '-');
6738+ if (p)
6739+ *p = '\0';
6740+ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 6741+ if (unlikely(err))
6742+ goto out;
acd2b654
AM
6743+ bindex = l;
6744+ idx = 0;
6745+ if (p) {
6746+ err = kstrtol(p + 1, 10, &l);
6747+ if (unlikely(err))
6748+ goto out;
6749+ idx = l;
6750+ }
1facf9fc 6751+
acd2b654 6752+ err = -ENOENT;
1facf9fc 6753+ sbinfo = inode->i_private;
6754+ sb = sbinfo->si_sb;
6755+ si_noflush_read_lock(sb);
acd2b654
AM
6756+ if (unlikely(bindex < 0 || bindex > au_sbbot(sb)))
6757+ goto out_si;
6758+ br = au_sbr(sb, bindex);
6759+ xi = br->br_xino;
6760+ if (unlikely(idx >= xi->xi_nfile))
6761+ goto out_si;
6762+ xf = au_xino_file(xi, idx);
6763+ if (xf)
062440b3
AM
6764+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1,
6765+ au_xino_count(br));
1facf9fc 6766+
acd2b654
AM
6767+out_si:
6768+ si_read_unlock(sb);
4f0767ce 6769+out:
acd2b654 6770+ AuTraceErr(err);
1facf9fc 6771+ return err;
6772+}
6773+
6774+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 6775+ .owner = THIS_MODULE,
1facf9fc 6776+ .open = dbgaufs_xino_open,
6777+ .release = dbgaufs_xi_release,
6778+ .read = dbgaufs_xi_read
6779+};
6780+
062440b3
AM
6781+void dbgaufs_xino_del(struct au_branch *br)
6782+{
6783+ struct dentry *dbgaufs;
6784+
6785+ dbgaufs = br->br_dbgaufs;
6786+ if (!dbgaufs)
6787+ return;
6788+
6789+ br->br_dbgaufs = NULL;
6790+ /* debugfs acquires the parent i_mutex */
6791+ lockdep_off();
6792+ debugfs_remove(dbgaufs);
6793+ lockdep_on();
6794+}
6795+
1facf9fc 6796+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
6797+{
5afbbe0d 6798+ aufs_bindex_t bbot;
1facf9fc 6799+ struct au_branch *br;
1facf9fc 6800+
6801+ if (!au_sbi(sb)->si_dbgaufs)
6802+ return;
6803+
5afbbe0d
AM
6804+ bbot = au_sbbot(sb);
6805+ for (; bindex <= bbot; bindex++) {
1facf9fc 6806+ br = au_sbr(sb, bindex);
062440b3
AM
6807+ dbgaufs_xino_del(br);
6808+ }
6809+}
6810+
acd2b654
AM
6811+static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex,
6812+ unsigned int idx, struct dentry *parent,
6813+ struct au_sbinfo *sbinfo)
062440b3
AM
6814+{
6815+ struct au_branch *br;
6816+ struct dentry *d;
acd2b654
AM
6817+ /* "xi" bindex(5) "-" idx(2) NULL */
6818+ char name[sizeof(DbgaufsXi_PREFIX) + 8];
062440b3 6819+
acd2b654
AM
6820+ if (!idx)
6821+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
6822+ else
6823+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u",
6824+ bindex, idx);
062440b3
AM
6825+ br = au_sbr(sb, bindex);
6826+ if (br->br_dbgaufs) {
6827+ struct qstr qstr = QSTR_INIT(name, strlen(name));
6828+
6829+ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) {
6830+ /* debugfs acquires the parent i_mutex */
6831+ lockdep_off();
6832+ d = debugfs_rename(parent, br->br_dbgaufs, parent,
6833+ name);
6834+ lockdep_on();
6835+ if (unlikely(!d))
6836+ pr_warn("failed renaming %pd/%s, ignored.\n",
6837+ parent, name);
6838+ }
6839+ } else {
e2f27e51 6840+ lockdep_off();
062440b3
AM
6841+ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
6842+ sbinfo, &dbgaufs_xino_fop);
e2f27e51 6843+ lockdep_on();
062440b3 6844+ if (unlikely(!br->br_dbgaufs))
acd2b654 6845+ pr_warn("failed creating %pd/%s, ignored.\n",
062440b3 6846+ parent, name);
1facf9fc 6847+ }
6848+}
6849+
acd2b654
AM
6850+static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex,
6851+ struct dentry *parent, struct au_sbinfo *sbinfo)
6852+{
6853+ struct au_branch *br;
6854+ struct au_xino *xi;
6855+ unsigned int u;
6856+
6857+ br = au_sbr(sb, bindex);
6858+ xi = br->br_xino;
6859+ for (u = 0; u < xi->xi_nfile; u++)
6860+ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo);
6861+}
6862+
062440b3 6863+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown)
1facf9fc 6864+{
6865+ struct au_sbinfo *sbinfo;
6866+ struct dentry *parent;
5afbbe0d 6867+ aufs_bindex_t bbot;
062440b3
AM
6868+
6869+ if (!au_opt_test(au_mntflags(sb), XINO))
6870+ return;
1facf9fc 6871+
6872+ sbinfo = au_sbi(sb);
6873+ parent = sbinfo->si_dbgaufs;
6874+ if (!parent)
6875+ return;
6876+
5afbbe0d 6877+ bbot = au_sbbot(sb);
062440b3
AM
6878+ if (topdown)
6879+ for (; bindex <= bbot; bindex++)
6880+ dbgaufs_br_add(sb, bindex, parent, sbinfo);
6881+ else
6882+ for (; bbot >= bindex; bbot--)
6883+ dbgaufs_br_add(sb, bbot, parent, sbinfo);
1facf9fc 6884+}
6885+
6886+/* ---------------------------------------------------------------------- */
6887+
6888+#ifdef CONFIG_AUFS_EXPORT
6889+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
6890+{
6891+ int err;
6892+ struct au_sbinfo *sbinfo;
6893+ struct super_block *sb;
6894+
6895+ sbinfo = inode->i_private;
6896+ sb = sbinfo->si_sb;
6897+ si_noflush_read_lock(sb);
062440b3 6898+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6899+ si_read_unlock(sb);
6900+ return err;
6901+}
6902+
6903+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 6904+ .owner = THIS_MODULE,
1facf9fc 6905+ .open = dbgaufs_xigen_open,
6906+ .release = dbgaufs_xi_release,
6907+ .read = dbgaufs_xi_read
6908+};
6909+
6910+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6911+{
6912+ int err;
6913+
dece6358 6914+ /*
c1595e42 6915+ * This function is a dynamic '__init' function actually,
dece6358
AM
6916+ * so the tiny check for si_rwsem is unnecessary.
6917+ */
6918+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6919+
1facf9fc 6920+ err = -EIO;
6921+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
6922+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6923+ &dbgaufs_xigen_fop);
6924+ if (sbinfo->si_dbgaufs_xigen)
6925+ err = 0;
6926+
6927+ return err;
6928+}
6929+#else
6930+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6931+{
6932+ return 0;
6933+}
6934+#endif /* CONFIG_AUFS_EXPORT */
6935+
6936+/* ---------------------------------------------------------------------- */
6937+
6938+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
6939+{
dece6358 6940+ /*
7e9cd9fe 6941+ * This function is a dynamic '__fin' function actually,
dece6358
AM
6942+ * so the tiny check for si_rwsem is unnecessary.
6943+ */
6944+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6945+
1facf9fc 6946+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
6947+ sbinfo->si_dbgaufs = NULL;
1facf9fc 6948+}
6949+
6950+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
6951+{
6952+ int err;
6953+ char name[SysaufsSiNameLen];
6954+
dece6358 6955+ /*
c1595e42 6956+ * This function is a dynamic '__init' function actually,
dece6358
AM
6957+ * so the tiny check for si_rwsem is unnecessary.
6958+ */
6959+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6960+
1facf9fc 6961+ err = -ENOENT;
6962+ if (!dbgaufs) {
6963+ AuErr1("/debug/aufs is uninitialized\n");
6964+ goto out;
6965+ }
6966+
6967+ err = -EIO;
6968+ sysaufs_name(sbinfo, name);
6969+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
6970+ if (unlikely(!sbinfo->si_dbgaufs))
6971+ goto out;
1facf9fc 6972+
062440b3 6973+ /* regardless plink/noplink option */
86dc4139
AM
6974+ sbinfo->si_dbgaufs_plink = debugfs_create_file
6975+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6976+ &dbgaufs_plink_fop);
6977+ if (unlikely(!sbinfo->si_dbgaufs_plink))
6978+ goto out_dir;
6979+
062440b3
AM
6980+ /* regardless xino/noxino option */
6981+ sbinfo->si_dbgaufs_xib = debugfs_create_file
6982+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6983+ &dbgaufs_xib_fop);
6984+ if (unlikely(!sbinfo->si_dbgaufs_xib))
6985+ goto out_dir;
6986+
1facf9fc 6987+ err = dbgaufs_xigen_init(sbinfo);
6988+ if (!err)
6989+ goto out; /* success */
6990+
4f0767ce 6991+out_dir:
1facf9fc 6992+ dbgaufs_si_fin(sbinfo);
4f0767ce 6993+out:
062440b3
AM
6994+ if (unlikely(err))
6995+ pr_err("debugfs/aufs failed\n");
1facf9fc 6996+ return err;
6997+}
6998+
6999+/* ---------------------------------------------------------------------- */
7000+
7001+void dbgaufs_fin(void)
7002+{
7003+ debugfs_remove(dbgaufs);
7004+}
7005+
7006+int __init dbgaufs_init(void)
7007+{
7008+ int err;
7009+
7010+ err = -EIO;
7011+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
7012+ if (dbgaufs)
7013+ err = 0;
7014+ return err;
7015+}
7f207e10 7016diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
eca34b5c
AM
7017--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
7018+++ linux/fs/aufs/dbgaufs.h 2019-07-11 15:42:14.462237786 +0200
062440b3
AM
7019@@ -0,0 +1,53 @@
7020+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7021+/*
ba1aed25 7022+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7023+ *
7024+ * This program, aufs is free software; you can redistribute it and/or modify
7025+ * it under the terms of the GNU General Public License as published by
7026+ * the Free Software Foundation; either version 2 of the License, or
7027+ * (at your option) any later version.
dece6358
AM
7028+ *
7029+ * This program is distributed in the hope that it will be useful,
7030+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7031+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7032+ * GNU General Public License for more details.
7033+ *
7034+ * You should have received a copy of the GNU General Public License
523b37e3 7035+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7036+ */
7037+
7038+/*
7039+ * debugfs interface
7040+ */
7041+
7042+#ifndef __DBGAUFS_H__
7043+#define __DBGAUFS_H__
7044+
7045+#ifdef __KERNEL__
7046+
dece6358 7047+struct super_block;
1facf9fc 7048+struct au_sbinfo;
062440b3 7049+struct au_branch;
dece6358 7050+
1facf9fc 7051+#ifdef CONFIG_DEBUG_FS
7052+/* dbgaufs.c */
062440b3 7053+void dbgaufs_xino_del(struct au_branch *br);
1facf9fc 7054+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
062440b3 7055+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown);
1facf9fc 7056+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
7057+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
7058+void dbgaufs_fin(void);
7059+int __init dbgaufs_init(void);
1facf9fc 7060+#else
062440b3 7061+AuStubVoid(dbgaufs_xino_del, struct au_branch *br)
4a4d8108 7062+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
062440b3
AM
7063+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex,
7064+ int topdown)
4a4d8108
AM
7065+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
7066+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
7067+AuStubVoid(dbgaufs_fin, void)
7068+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 7069+#endif /* CONFIG_DEBUG_FS */
7070+
7071+#endif /* __KERNEL__ */
7072+#endif /* __DBGAUFS_H__ */
7f207e10 7073diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
eca34b5c
AM
7074--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
7075+++ linux/fs/aufs/dcsub.c 2019-07-11 15:42:14.462237786 +0200
cd7a4cd9
AM
7076@@ -0,0 +1,225 @@
7077+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7078+/*
ba1aed25 7079+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7080+ *
7081+ * This program, aufs is free software; you can redistribute it and/or modify
7082+ * it under the terms of the GNU General Public License as published by
7083+ * the Free Software Foundation; either version 2 of the License, or
7084+ * (at your option) any later version.
dece6358
AM
7085+ *
7086+ * This program is distributed in the hope that it will be useful,
7087+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7088+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7089+ * GNU General Public License for more details.
7090+ *
7091+ * You should have received a copy of the GNU General Public License
523b37e3 7092+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7093+ */
7094+
7095+/*
7096+ * sub-routines for dentry cache
7097+ */
7098+
7099+#include "aufs.h"
7100+
7101+static void au_dpage_free(struct au_dpage *dpage)
7102+{
7103+ int i;
7104+ struct dentry **p;
7105+
7106+ p = dpage->dentries;
7107+ for (i = 0; i < dpage->ndentry; i++)
7108+ dput(*p++);
1c60b727 7109+ free_page((unsigned long)dpage->dentries);
1facf9fc 7110+}
7111+
7112+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
7113+{
7114+ int err;
7115+ void *p;
7116+
7117+ err = -ENOMEM;
7118+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
7119+ if (unlikely(!dpages->dpages))
7120+ goto out;
7121+
7122+ p = (void *)__get_free_page(gfp);
7123+ if (unlikely(!p))
7124+ goto out_dpages;
7125+
7126+ dpages->dpages[0].ndentry = 0;
7127+ dpages->dpages[0].dentries = p;
7128+ dpages->ndpage = 1;
7129+ return 0; /* success */
7130+
4f0767ce 7131+out_dpages:
9f237c51 7132+ au_kfree_try_rcu(dpages->dpages);
4f0767ce 7133+out:
1facf9fc 7134+ return err;
7135+}
7136+
7137+void au_dpages_free(struct au_dcsub_pages *dpages)
7138+{
7139+ int i;
7140+ struct au_dpage *p;
7141+
7142+ p = dpages->dpages;
7143+ for (i = 0; i < dpages->ndpage; i++)
7144+ au_dpage_free(p++);
9f237c51 7145+ au_kfree_try_rcu(dpages->dpages);
1facf9fc 7146+}
7147+
7148+static int au_dpages_append(struct au_dcsub_pages *dpages,
7149+ struct dentry *dentry, gfp_t gfp)
7150+{
7151+ int err, sz;
7152+ struct au_dpage *dpage;
7153+ void *p;
7154+
7155+ dpage = dpages->dpages + dpages->ndpage - 1;
7156+ sz = PAGE_SIZE / sizeof(dentry);
7157+ if (unlikely(dpage->ndentry >= sz)) {
7158+ AuLabel(new dpage);
7159+ err = -ENOMEM;
7160+ sz = dpages->ndpage * sizeof(*dpages->dpages);
7161+ p = au_kzrealloc(dpages->dpages, sz,
e2f27e51
AM
7162+ sz + sizeof(*dpages->dpages), gfp,
7163+ /*may_shrink*/0);
1facf9fc 7164+ if (unlikely(!p))
7165+ goto out;
7166+
7167+ dpages->dpages = p;
7168+ dpage = dpages->dpages + dpages->ndpage;
7169+ p = (void *)__get_free_page(gfp);
7170+ if (unlikely(!p))
7171+ goto out;
7172+
7173+ dpage->ndentry = 0;
7174+ dpage->dentries = p;
7175+ dpages->ndpage++;
7176+ }
7177+
c1595e42 7178+ AuDebugOn(au_dcount(dentry) <= 0);
027c5e7a 7179+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 7180+ return 0; /* success */
7181+
4f0767ce 7182+out:
1facf9fc 7183+ return err;
7184+}
7185+
c1595e42
JR
7186+/* todo: BAD approach */
7187+/* copied from linux/fs/dcache.c */
7188+enum d_walk_ret {
7189+ D_WALK_CONTINUE,
7190+ D_WALK_QUIT,
7191+ D_WALK_NORETRY,
7192+ D_WALK_SKIP,
7193+};
7194+
7195+extern void d_walk(struct dentry *parent, void *data,
cd7a4cd9 7196+ enum d_walk_ret (*enter)(void *, struct dentry *));
c1595e42
JR
7197+
7198+struct ac_dpages_arg {
1facf9fc 7199+ int err;
c1595e42
JR
7200+ struct au_dcsub_pages *dpages;
7201+ struct super_block *sb;
7202+ au_dpages_test test;
7203+ void *arg;
7204+};
1facf9fc 7205+
c1595e42
JR
7206+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry)
7207+{
7208+ enum d_walk_ret ret;
7209+ struct ac_dpages_arg *arg = _arg;
1facf9fc 7210+
c1595e42
JR
7211+ ret = D_WALK_CONTINUE;
7212+ if (dentry->d_sb == arg->sb
7213+ && !IS_ROOT(dentry)
7214+ && au_dcount(dentry) > 0
7215+ && au_di(dentry)
7216+ && (!arg->test || arg->test(dentry, arg->arg))) {
7217+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC);
7218+ if (unlikely(arg->err))
7219+ ret = D_WALK_QUIT;
1facf9fc 7220+ }
7221+
c1595e42
JR
7222+ return ret;
7223+}
027c5e7a 7224+
c1595e42
JR
7225+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7226+ au_dpages_test test, void *arg)
7227+{
7228+ struct ac_dpages_arg args = {
7229+ .err = 0,
7230+ .dpages = dpages,
7231+ .sb = root->d_sb,
7232+ .test = test,
7233+ .arg = arg
7234+ };
027c5e7a 7235+
cd7a4cd9 7236+ d_walk(root, &args, au_call_dpages_append);
c1595e42
JR
7237+
7238+ return args.err;
1facf9fc 7239+}
7240+
7241+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7242+ int do_include, au_dpages_test test, void *arg)
7243+{
7244+ int err;
7245+
7246+ err = 0;
027c5e7a
AM
7247+ write_seqlock(&rename_lock);
7248+ spin_lock(&dentry->d_lock);
7249+ if (do_include
c1595e42 7250+ && au_dcount(dentry) > 0
027c5e7a 7251+ && (!test || test(dentry, arg)))
1facf9fc 7252+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7253+ spin_unlock(&dentry->d_lock);
7254+ if (unlikely(err))
7255+ goto out;
7256+
7257+ /*
523b37e3 7258+ * RCU for vfsmount is unnecessary since this is a traverse in a single
027c5e7a
AM
7259+ * mount
7260+ */
1facf9fc 7261+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
7262+ dentry = dentry->d_parent; /* rename_lock is locked */
7263+ spin_lock(&dentry->d_lock);
c1595e42 7264+ if (au_dcount(dentry) > 0
027c5e7a 7265+ && (!test || test(dentry, arg)))
1facf9fc 7266+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7267+ spin_unlock(&dentry->d_lock);
7268+ if (unlikely(err))
7269+ break;
1facf9fc 7270+ }
7271+
4f0767ce 7272+out:
027c5e7a 7273+ write_sequnlock(&rename_lock);
1facf9fc 7274+ return err;
7275+}
7276+
027c5e7a
AM
7277+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
7278+{
7279+ return au_di(dentry) && dentry->d_sb == arg;
7280+}
7281+
7282+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7283+ struct dentry *dentry, int do_include)
7284+{
7285+ return au_dcsub_pages_rev(dpages, dentry, do_include,
7286+ au_dcsub_dpages_aufs, dentry->d_sb);
7287+}
7288+
4a4d8108 7289+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 7290+{
4a4d8108
AM
7291+ struct path path[2] = {
7292+ {
7293+ .dentry = d1
7294+ },
7295+ {
7296+ .dentry = d2
7297+ }
7298+ };
1facf9fc 7299+
4a4d8108 7300+ return path_is_under(path + 0, path + 1);
1facf9fc 7301+}
7f207e10 7302diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
eca34b5c
AM
7303--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
7304+++ linux/fs/aufs/dcsub.h 2019-07-11 15:42:14.462237786 +0200
062440b3
AM
7305@@ -0,0 +1,137 @@
7306+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7307+/*
ba1aed25 7308+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7309+ *
7310+ * This program, aufs is free software; you can redistribute it and/or modify
7311+ * it under the terms of the GNU General Public License as published by
7312+ * the Free Software Foundation; either version 2 of the License, or
7313+ * (at your option) any later version.
dece6358
AM
7314+ *
7315+ * This program is distributed in the hope that it will be useful,
7316+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7317+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7318+ * GNU General Public License for more details.
7319+ *
7320+ * You should have received a copy of the GNU General Public License
523b37e3 7321+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7322+ */
7323+
7324+/*
7325+ * sub-routines for dentry cache
7326+ */
7327+
7328+#ifndef __AUFS_DCSUB_H__
7329+#define __AUFS_DCSUB_H__
7330+
7331+#ifdef __KERNEL__
7332+
7f207e10 7333+#include <linux/dcache.h>
027c5e7a 7334+#include <linux/fs.h>
dece6358 7335+
1facf9fc 7336+struct au_dpage {
7337+ int ndentry;
7338+ struct dentry **dentries;
7339+};
7340+
7341+struct au_dcsub_pages {
7342+ int ndpage;
7343+ struct au_dpage *dpages;
7344+};
7345+
7346+/* ---------------------------------------------------------------------- */
7347+
7f207e10 7348+/* dcsub.c */
1facf9fc 7349+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
7350+void au_dpages_free(struct au_dcsub_pages *dpages);
7351+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
7352+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7353+ au_dpages_test test, void *arg);
7354+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7355+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
7356+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7357+ struct dentry *dentry, int do_include);
4a4d8108 7358+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 7359+
7f207e10
AM
7360+/* ---------------------------------------------------------------------- */
7361+
523b37e3
AM
7362+/*
7363+ * todo: in linux-3.13, several similar (but faster) helpers are added to
7364+ * include/linux/dcache.h. Try them (in the future).
7365+ */
7366+
027c5e7a
AM
7367+static inline int au_d_hashed_positive(struct dentry *d)
7368+{
7369+ int err;
5527c038 7370+ struct inode *inode = d_inode(d);
076b876e 7371+
027c5e7a 7372+ err = 0;
5527c038
JR
7373+ if (unlikely(d_unhashed(d)
7374+ || d_is_negative(d)
7375+ || !inode->i_nlink))
027c5e7a
AM
7376+ err = -ENOENT;
7377+ return err;
7378+}
7379+
38d290e6
JR
7380+static inline int au_d_linkable(struct dentry *d)
7381+{
7382+ int err;
5527c038 7383+ struct inode *inode = d_inode(d);
076b876e 7384+
38d290e6
JR
7385+ err = au_d_hashed_positive(d);
7386+ if (err
5527c038 7387+ && d_is_positive(d)
38d290e6
JR
7388+ && (inode->i_state & I_LINKABLE))
7389+ err = 0;
7390+ return err;
7391+}
7392+
027c5e7a
AM
7393+static inline int au_d_alive(struct dentry *d)
7394+{
7395+ int err;
7396+ struct inode *inode;
076b876e 7397+
027c5e7a
AM
7398+ err = 0;
7399+ if (!IS_ROOT(d))
7400+ err = au_d_hashed_positive(d);
7401+ else {
5527c038
JR
7402+ inode = d_inode(d);
7403+ if (unlikely(d_unlinked(d)
7404+ || d_is_negative(d)
7405+ || !inode->i_nlink))
027c5e7a
AM
7406+ err = -ENOENT;
7407+ }
7408+ return err;
7409+}
7410+
7411+static inline int au_alive_dir(struct dentry *d)
7f207e10 7412+{
027c5e7a 7413+ int err;
076b876e 7414+
027c5e7a 7415+ err = au_d_alive(d);
5527c038 7416+ if (unlikely(err || IS_DEADDIR(d_inode(d))))
027c5e7a
AM
7417+ err = -ENOENT;
7418+ return err;
7f207e10
AM
7419+}
7420+
38d290e6
JR
7421+static inline int au_qstreq(struct qstr *a, struct qstr *b)
7422+{
7423+ return a->len == b->len
7424+ && !memcmp(a->name, b->name, a->len);
7425+}
7426+
7e9cd9fe
AM
7427+/*
7428+ * by the commit
7429+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without
7430+ * taking d_lock
7431+ * the type of d_lockref.count became int, but the inlined function d_count()
7432+ * still returns unsigned int.
7433+ * I don't know why. Maybe it is for every d_count() users?
7434+ * Anyway au_dcount() lives on.
7435+ */
c1595e42
JR
7436+static inline int au_dcount(struct dentry *d)
7437+{
7438+ return (int)d_count(d);
7439+}
7440+
1facf9fc 7441+#endif /* __KERNEL__ */
7442+#endif /* __AUFS_DCSUB_H__ */
7f207e10 7443diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
eca34b5c
AM
7444--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
7445+++ linux/fs/aufs/debug.c 2019-07-11 15:42:14.462237786 +0200
eca801bf 7446@@ -0,0 +1,441 @@
cd7a4cd9 7447+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7448+/*
ba1aed25 7449+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7450+ *
7451+ * This program, aufs is free software; you can redistribute it and/or modify
7452+ * it under the terms of the GNU General Public License as published by
7453+ * the Free Software Foundation; either version 2 of the License, or
7454+ * (at your option) any later version.
dece6358
AM
7455+ *
7456+ * This program is distributed in the hope that it will be useful,
7457+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7458+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7459+ * GNU General Public License for more details.
7460+ *
7461+ * You should have received a copy of the GNU General Public License
523b37e3 7462+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7463+ */
7464+
7465+/*
7466+ * debug print functions
7467+ */
7468+
eca801bf 7469+#include <linux/iversion.h>
1facf9fc 7470+#include "aufs.h"
7471+
392086de
AM
7472+/* Returns 0, or -errno. arg is in kp->arg. */
7473+static int param_atomic_t_set(const char *val, const struct kernel_param *kp)
7474+{
7475+ int err, n;
7476+
7477+ err = kstrtoint(val, 0, &n);
7478+ if (!err) {
7479+ if (n > 0)
7480+ au_debug_on();
7481+ else
7482+ au_debug_off();
7483+ }
7484+ return err;
7485+}
7486+
7487+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
7488+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp)
7489+{
7490+ atomic_t *a;
7491+
7492+ a = kp->arg;
7493+ return sprintf(buffer, "%d", atomic_read(a));
7494+}
7495+
7496+static struct kernel_param_ops param_ops_atomic_t = {
7497+ .set = param_atomic_t_set,
7498+ .get = param_atomic_t_get
7499+ /* void (*free)(void *arg) */
7500+};
7501+
7502+atomic_t aufs_debug = ATOMIC_INIT(0);
1facf9fc 7503+MODULE_PARM_DESC(debug, "debug print");
cd7a4cd9 7504+module_param_named(debug, aufs_debug, atomic_t, 0664);
1facf9fc 7505+
c1595e42 7506+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */
1facf9fc 7507+char *au_plevel = KERN_DEBUG;
e49829fe
JR
7508+#define dpri(fmt, ...) do { \
7509+ if ((au_plevel \
7510+ && strcmp(au_plevel, KERN_DEBUG)) \
7511+ || au_debug_test()) \
7512+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 7513+} while (0)
7514+
7515+/* ---------------------------------------------------------------------- */
7516+
7517+void au_dpri_whlist(struct au_nhash *whlist)
7518+{
7519+ unsigned long ul, n;
7520+ struct hlist_head *head;
c06a8ce3 7521+ struct au_vdir_wh *pos;
1facf9fc 7522+
7523+ n = whlist->nh_num;
7524+ head = whlist->nh_head;
7525+ for (ul = 0; ul < n; ul++) {
c06a8ce3 7526+ hlist_for_each_entry(pos, head, wh_hash)
1facf9fc 7527+ dpri("b%d, %.*s, %d\n",
c06a8ce3
AM
7528+ pos->wh_bindex,
7529+ pos->wh_str.len, pos->wh_str.name,
7530+ pos->wh_str.len);
1facf9fc 7531+ head++;
7532+ }
7533+}
7534+
7535+void au_dpri_vdir(struct au_vdir *vdir)
7536+{
7537+ unsigned long ul;
7538+ union au_vdir_deblk_p p;
7539+ unsigned char *o;
7540+
7541+ if (!vdir || IS_ERR(vdir)) {
7542+ dpri("err %ld\n", PTR_ERR(vdir));
7543+ return;
7544+ }
7545+
be118d29 7546+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n",
1facf9fc 7547+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
7548+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
7549+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
7550+ p.deblk = vdir->vd_deblk[ul];
7551+ o = p.deblk;
7552+ dpri("[%lu]: %p\n", ul, o);
7553+ }
7554+}
7555+
53392da6 7556+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 7557+ struct dentry *wh)
7558+{
7559+ char *n = NULL;
7560+ int l = 0;
7561+
7562+ if (!inode || IS_ERR(inode)) {
7563+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
7564+ return -1;
7565+ }
7566+
c2b27bf2 7567+ /* the type of i_blocks depends upon CONFIG_LBDAF */
1facf9fc 7568+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
7569+ && sizeof(inode->i_blocks) != sizeof(u64));
7570+ if (wh) {
7571+ n = (void *)wh->d_name.name;
7572+ l = wh->d_name.len;
7573+ }
7574+
53392da6
AM
7575+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
7576+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
7577+ bindex, inode,
1facf9fc 7578+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
7579+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
7580+ i_size_read(inode), (unsigned long long)inode->i_blocks,
cd7a4cd9 7581+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 7582+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
be118d29 7583+ inode->i_state, inode->i_flags, inode_peek_iversion(inode),
b752ccd1 7584+ inode->i_generation,
1facf9fc 7585+ l ? ", wh " : "", l, n);
7586+ return 0;
7587+}
7588+
7589+void au_dpri_inode(struct inode *inode)
7590+{
7591+ struct au_iinfo *iinfo;
5afbbe0d 7592+ struct au_hinode *hi;
1facf9fc 7593+ aufs_bindex_t bindex;
53392da6 7594+ int err, hn;
1facf9fc 7595+
53392da6 7596+ err = do_pri_inode(-1, inode, -1, NULL);
5afbbe0d 7597+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode))
1facf9fc 7598+ return;
7599+
7600+ iinfo = au_ii(inode);
5afbbe0d
AM
7601+ dpri("i-1: btop %d, bbot %d, gen %d\n",
7602+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL));
7603+ if (iinfo->ii_btop < 0)
1facf9fc 7604+ return;
53392da6 7605+ hn = 0;
5afbbe0d
AM
7606+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) {
7607+ hi = au_hinode(iinfo, bindex);
7608+ hn = !!au_hn(hi);
7609+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry);
53392da6 7610+ }
1facf9fc 7611+}
7612+
2cbb1c4b
JR
7613+void au_dpri_dalias(struct inode *inode)
7614+{
7615+ struct dentry *d;
7616+
7617+ spin_lock(&inode->i_lock);
c1595e42 7618+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias)
2cbb1c4b
JR
7619+ au_dpri_dentry(d);
7620+ spin_unlock(&inode->i_lock);
7621+}
7622+
1facf9fc 7623+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
7624+{
7625+ struct dentry *wh = NULL;
53392da6 7626+ int hn;
5afbbe0d 7627+ struct inode *inode;
076b876e 7628+ struct au_iinfo *iinfo;
5afbbe0d 7629+ struct au_hinode *hi;
1facf9fc 7630+
7631+ if (!dentry || IS_ERR(dentry)) {
7632+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
7633+ return -1;
7634+ }
7635+ /* do not call dget_parent() here */
027c5e7a 7636+ /* note: access d_xxx without d_lock */
523b37e3
AM
7637+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n",
7638+ bindex, dentry, dentry,
1facf9fc 7639+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
c1595e42 7640+ au_dcount(dentry), dentry->d_flags,
523b37e3 7641+ d_unhashed(dentry) ? "un" : "");
53392da6 7642+ hn = -1;
5afbbe0d
AM
7643+ inode = NULL;
7644+ if (d_is_positive(dentry))
7645+ inode = d_inode(dentry);
7646+ if (inode
7647+ && au_test_aufs(dentry->d_sb)
7648+ && bindex >= 0
7649+ && !au_is_bad_inode(inode)) {
7650+ iinfo = au_ii(inode);
7651+ hi = au_hinode(iinfo, bindex);
7652+ hn = !!au_hn(hi);
7653+ wh = hi->hi_whdentry;
7654+ }
7655+ do_pri_inode(bindex, inode, hn, wh);
1facf9fc 7656+ return 0;
7657+}
7658+
7659+void au_dpri_dentry(struct dentry *dentry)
7660+{
7661+ struct au_dinfo *dinfo;
7662+ aufs_bindex_t bindex;
7663+ int err;
7664+
7665+ err = do_pri_dentry(-1, dentry);
7666+ if (err || !au_test_aufs(dentry->d_sb))
7667+ return;
7668+
7669+ dinfo = au_di(dentry);
7670+ if (!dinfo)
7671+ return;
5afbbe0d
AM
7672+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n",
7673+ dinfo->di_btop, dinfo->di_bbot,
38d290e6
JR
7674+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry),
7675+ dinfo->di_tmpfile);
5afbbe0d 7676+ if (dinfo->di_btop < 0)
1facf9fc 7677+ return;
5afbbe0d
AM
7678+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++)
7679+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry);
1facf9fc 7680+}
7681+
7682+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
7683+{
7684+ char a[32];
7685+
7686+ if (!file || IS_ERR(file)) {
7687+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
7688+ return -1;
7689+ }
7690+ a[0] = 0;
7691+ if (bindex < 0
b912730e 7692+ && !IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7693+ && au_test_aufs(file->f_path.dentry->d_sb)
1facf9fc 7694+ && au_fi(file))
e49829fe 7695+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 7696+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 7697+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 7698+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 7699+ file->f_version, file->f_pos, a);
b912730e 7700+ if (!IS_ERR_OR_NULL(file->f_path.dentry))
2000de60 7701+ do_pri_dentry(bindex, file->f_path.dentry);
1facf9fc 7702+ return 0;
7703+}
7704+
7705+void au_dpri_file(struct file *file)
7706+{
7707+ struct au_finfo *finfo;
4a4d8108
AM
7708+ struct au_fidir *fidir;
7709+ struct au_hfile *hfile;
1facf9fc 7710+ aufs_bindex_t bindex;
7711+ int err;
7712+
7713+ err = do_pri_file(-1, file);
2000de60 7714+ if (err
b912730e 7715+ || IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7716+ || !au_test_aufs(file->f_path.dentry->d_sb))
1facf9fc 7717+ return;
7718+
7719+ finfo = au_fi(file);
7720+ if (!finfo)
7721+ return;
4a4d8108 7722+ if (finfo->fi_btop < 0)
1facf9fc 7723+ return;
4a4d8108
AM
7724+ fidir = finfo->fi_hdir;
7725+ if (!fidir)
7726+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
7727+ else
e49829fe
JR
7728+ for (bindex = finfo->fi_btop;
7729+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
7730+ bindex++) {
7731+ hfile = fidir->fd_hfile + bindex;
7732+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
7733+ }
1facf9fc 7734+}
7735+
7736+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
7737+{
7738+ struct vfsmount *mnt;
7739+ struct super_block *sb;
7740+
7741+ if (!br || IS_ERR(br))
7742+ goto out;
86dc4139 7743+ mnt = au_br_mnt(br);
1facf9fc 7744+ if (!mnt || IS_ERR(mnt))
7745+ goto out;
7746+ sb = mnt->mnt_sb;
7747+ if (!sb || IS_ERR(sb))
7748+ goto out;
7749+
acd2b654 7750+ dpri("s%d: {perm 0x%x, id %d, wbr %p}, "
b752ccd1 7751+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 7752+ "xino %d\n",
acd2b654
AM
7753+ bindex, br->br_perm, br->br_id, br->br_wbr,
7754+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 7755+ sb->s_flags, sb->s_count,
acd2b654
AM
7756+ atomic_read(&sb->s_active),
7757+ !!au_xino_file(br->br_xino, /*idx*/-1));
1facf9fc 7758+ return 0;
7759+
4f0767ce 7760+out:
1facf9fc 7761+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
7762+ return -1;
7763+}
7764+
7765+void au_dpri_sb(struct super_block *sb)
7766+{
7767+ struct au_sbinfo *sbinfo;
7768+ aufs_bindex_t bindex;
7769+ int err;
acd2b654 7770+ /* to reduce stack size */
1facf9fc 7771+ struct {
7772+ struct vfsmount mnt;
7773+ struct au_branch fake;
7774+ } *a;
7775+
7776+ /* this function can be called from magic sysrq */
7777+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
7778+ if (unlikely(!a)) {
7779+ dpri("no memory\n");
7780+ return;
7781+ }
7782+
7783+ a->mnt.mnt_sb = sb;
86dc4139 7784+ a->fake.br_path.mnt = &a->mnt;
1facf9fc 7785+ err = do_pri_br(-1, &a->fake);
9f237c51 7786+ au_kfree_rcu(a);
1facf9fc 7787+ dpri("dev 0x%x\n", sb->s_dev);
7788+ if (err || !au_test_aufs(sb))
7789+ return;
7790+
7791+ sbinfo = au_sbi(sb);
7792+ if (!sbinfo)
7793+ return;
f0c0a007
AM
7794+ dpri("nw %d, gen %u, kobj %d\n",
7795+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
521ced18 7796+ kref_read(&sbinfo->si_kobj.kref));
5afbbe0d 7797+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++)
1facf9fc 7798+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
7799+}
7800+
7801+/* ---------------------------------------------------------------------- */
7802+
027c5e7a
AM
7803+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
7804+{
5527c038 7805+ struct inode *h_inode, *inode = d_inode(dentry);
027c5e7a 7806+ struct dentry *h_dentry;
5afbbe0d 7807+ aufs_bindex_t bindex, bbot, bi;
027c5e7a
AM
7808+
7809+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
7810+ return;
7811+
5afbbe0d
AM
7812+ bbot = au_dbbot(dentry);
7813+ bi = au_ibbot(inode);
7814+ if (bi < bbot)
7815+ bbot = bi;
7816+ bindex = au_dbtop(dentry);
7817+ bi = au_ibtop(inode);
027c5e7a
AM
7818+ if (bi > bindex)
7819+ bindex = bi;
7820+
5afbbe0d 7821+ for (; bindex <= bbot; bindex++) {
027c5e7a
AM
7822+ h_dentry = au_h_dptr(dentry, bindex);
7823+ if (!h_dentry)
7824+ continue;
7825+ h_inode = au_h_iptr(inode, bindex);
5527c038 7826+ if (unlikely(h_inode != d_inode(h_dentry))) {
392086de 7827+ au_debug_on();
027c5e7a
AM
7828+ AuDbg("b%d, %s:%d\n", bindex, func, line);
7829+ AuDbgDentry(dentry);
7830+ AuDbgInode(inode);
392086de 7831+ au_debug_off();
027c5e7a
AM
7832+ BUG();
7833+ }
7834+ }
7835+}
7836+
1facf9fc 7837+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
7838+{
7839+ int err, i, j;
7840+ struct au_dcsub_pages dpages;
7841+ struct au_dpage *dpage;
7842+ struct dentry **dentries;
7843+
7844+ err = au_dpages_init(&dpages, GFP_NOFS);
7845+ AuDebugOn(err);
027c5e7a 7846+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 7847+ AuDebugOn(err);
7848+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
7849+ dpage = dpages.dpages + i;
7850+ dentries = dpage->dentries;
7851+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 7852+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 7853+ }
7854+ au_dpages_free(&dpages);
7855+}
7856+
1facf9fc 7857+void au_dbg_verify_kthread(void)
7858+{
53392da6 7859+ if (au_wkq_test()) {
1facf9fc 7860+ au_dbg_blocked();
1e00d052
AM
7861+ /*
7862+ * It may be recursive, but udba=notify between two aufs mounts,
7863+ * where a single ro branch is shared, is not a problem.
7864+ */
7865+ /* WARN_ON(1); */
1facf9fc 7866+ }
7867+}
7868+
7869+/* ---------------------------------------------------------------------- */
7870+
1facf9fc 7871+int __init au_debug_init(void)
7872+{
7873+ aufs_bindex_t bindex;
7874+ struct au_vdir_destr destr;
7875+
7876+ bindex = -1;
7877+ AuDebugOn(bindex >= 0);
7878+
7879+ destr.len = -1;
7880+ AuDebugOn(destr.len < NAME_MAX);
7881+
7882+#ifdef CONFIG_4KSTACKS
0c3ec466 7883+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 7884+#endif
7885+
1facf9fc 7886+ return 0;
7887+}
7f207e10 7888diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
eca34b5c
AM
7889--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
7890+++ linux/fs/aufs/debug.h 2019-07-11 15:42:14.462237786 +0200
062440b3
AM
7891@@ -0,0 +1,226 @@
7892+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7893+/*
ba1aed25 7894+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7895+ *
7896+ * This program, aufs is free software; you can redistribute it and/or modify
7897+ * it under the terms of the GNU General Public License as published by
7898+ * the Free Software Foundation; either version 2 of the License, or
7899+ * (at your option) any later version.
dece6358
AM
7900+ *
7901+ * This program is distributed in the hope that it will be useful,
7902+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7903+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7904+ * GNU General Public License for more details.
7905+ *
7906+ * You should have received a copy of the GNU General Public License
523b37e3 7907+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7908+ */
7909+
7910+/*
7911+ * debug print functions
7912+ */
7913+
7914+#ifndef __AUFS_DEBUG_H__
7915+#define __AUFS_DEBUG_H__
7916+
7917+#ifdef __KERNEL__
7918+
392086de 7919+#include <linux/atomic.h>
4a4d8108
AM
7920+#include <linux/module.h>
7921+#include <linux/kallsyms.h>
1facf9fc 7922+#include <linux/sysrq.h>
4a4d8108 7923+
1facf9fc 7924+#ifdef CONFIG_AUFS_DEBUG
7925+#define AuDebugOn(a) BUG_ON(a)
7926+
7927+/* module parameter */
392086de
AM
7928+extern atomic_t aufs_debug;
7929+static inline void au_debug_on(void)
1facf9fc 7930+{
392086de
AM
7931+ atomic_inc(&aufs_debug);
7932+}
7933+static inline void au_debug_off(void)
7934+{
7935+ atomic_dec_if_positive(&aufs_debug);
1facf9fc 7936+}
7937+
7938+static inline int au_debug_test(void)
7939+{
392086de 7940+ return atomic_read(&aufs_debug) > 0;
1facf9fc 7941+}
7942+#else
7943+#define AuDebugOn(a) do {} while (0)
392086de
AM
7944+AuStubVoid(au_debug_on, void)
7945+AuStubVoid(au_debug_off, void)
4a4d8108 7946+AuStubInt0(au_debug_test, void)
1facf9fc 7947+#endif /* CONFIG_AUFS_DEBUG */
7948+
392086de
AM
7949+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t)
7950+
1facf9fc 7951+/* ---------------------------------------------------------------------- */
7952+
7953+/* debug print */
7954+
4a4d8108 7955+#define AuDbg(fmt, ...) do { \
1facf9fc 7956+ if (au_debug_test()) \
4a4d8108 7957+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 7958+} while (0)
4a4d8108
AM
7959+#define AuLabel(l) AuDbg(#l "\n")
7960+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
7961+#define AuWarn1(fmt, ...) do { \
1facf9fc 7962+ static unsigned char _c; \
7963+ if (!_c++) \
0c3ec466 7964+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 7965+} while (0)
7966+
4a4d8108 7967+#define AuErr1(fmt, ...) do { \
1facf9fc 7968+ static unsigned char _c; \
7969+ if (!_c++) \
4a4d8108 7970+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 7971+} while (0)
7972+
4a4d8108 7973+#define AuIOErr1(fmt, ...) do { \
1facf9fc 7974+ static unsigned char _c; \
7975+ if (!_c++) \
4a4d8108 7976+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 7977+} while (0)
7978+
7979+#define AuUnsupportMsg "This operation is not supported." \
7980+ " Please report this application to aufs-users ML."
4a4d8108
AM
7981+#define AuUnsupport(fmt, ...) do { \
7982+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 7983+ dump_stack(); \
7984+} while (0)
7985+
7986+#define AuTraceErr(e) do { \
7987+ if (unlikely((e) < 0)) \
7988+ AuDbg("err %d\n", (int)(e)); \
7989+} while (0)
7990+
7991+#define AuTraceErrPtr(p) do { \
7992+ if (IS_ERR(p)) \
7993+ AuDbg("err %ld\n", PTR_ERR(p)); \
7994+} while (0)
7995+
7996+/* dirty macros for debug print, use with "%.*s" and caution */
7997+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
1facf9fc 7998+
7999+/* ---------------------------------------------------------------------- */
8000+
dece6358 8001+struct dentry;
1facf9fc 8002+#ifdef CONFIG_AUFS_DEBUG
c1595e42 8003+extern struct mutex au_dbg_mtx;
1facf9fc 8004+extern char *au_plevel;
8005+struct au_nhash;
8006+void au_dpri_whlist(struct au_nhash *whlist);
8007+struct au_vdir;
8008+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 8009+struct inode;
1facf9fc 8010+void au_dpri_inode(struct inode *inode);
2cbb1c4b 8011+void au_dpri_dalias(struct inode *inode);
1facf9fc 8012+void au_dpri_dentry(struct dentry *dentry);
dece6358 8013+struct file;
1facf9fc 8014+void au_dpri_file(struct file *filp);
dece6358 8015+struct super_block;
1facf9fc 8016+void au_dpri_sb(struct super_block *sb);
8017+
027c5e7a
AM
8018+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
8019+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 8020+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 8021+void au_dbg_verify_kthread(void);
8022+
8023+int __init au_debug_init(void);
7e9cd9fe 8024+
1facf9fc 8025+#define AuDbgWhlist(w) do { \
c1595e42 8026+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8027+ AuDbg(#w "\n"); \
8028+ au_dpri_whlist(w); \
c1595e42 8029+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8030+} while (0)
8031+
8032+#define AuDbgVdir(v) do { \
c1595e42 8033+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8034+ AuDbg(#v "\n"); \
8035+ au_dpri_vdir(v); \
c1595e42 8036+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8037+} while (0)
8038+
8039+#define AuDbgInode(i) do { \
c1595e42 8040+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8041+ AuDbg(#i "\n"); \
8042+ au_dpri_inode(i); \
c1595e42 8043+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8044+} while (0)
8045+
2cbb1c4b 8046+#define AuDbgDAlias(i) do { \
c1595e42 8047+ mutex_lock(&au_dbg_mtx); \
2cbb1c4b
JR
8048+ AuDbg(#i "\n"); \
8049+ au_dpri_dalias(i); \
c1595e42 8050+ mutex_unlock(&au_dbg_mtx); \
2cbb1c4b
JR
8051+} while (0)
8052+
1facf9fc 8053+#define AuDbgDentry(d) do { \
c1595e42 8054+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8055+ AuDbg(#d "\n"); \
8056+ au_dpri_dentry(d); \
c1595e42 8057+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8058+} while (0)
8059+
8060+#define AuDbgFile(f) do { \
c1595e42 8061+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8062+ AuDbg(#f "\n"); \
8063+ au_dpri_file(f); \
c1595e42 8064+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8065+} while (0)
8066+
8067+#define AuDbgSb(sb) do { \
c1595e42 8068+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8069+ AuDbg(#sb "\n"); \
8070+ au_dpri_sb(sb); \
c1595e42 8071+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8072+} while (0)
8073+
4a4d8108
AM
8074+#define AuDbgSym(addr) do { \
8075+ char sym[KSYM_SYMBOL_LEN]; \
8076+ sprint_symbol(sym, (unsigned long)addr); \
8077+ AuDbg("%s\n", sym); \
8078+} while (0)
1facf9fc 8079+#else
027c5e7a 8080+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
8081+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
8082+AuStubVoid(au_dbg_verify_kthread, void)
8083+AuStubInt0(__init au_debug_init, void)
1facf9fc 8084+
1facf9fc 8085+#define AuDbgWhlist(w) do {} while (0)
8086+#define AuDbgVdir(v) do {} while (0)
8087+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 8088+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 8089+#define AuDbgDentry(d) do {} while (0)
8090+#define AuDbgFile(f) do {} while (0)
8091+#define AuDbgSb(sb) do {} while (0)
4a4d8108 8092+#define AuDbgSym(addr) do {} while (0)
1facf9fc 8093+#endif /* CONFIG_AUFS_DEBUG */
8094+
8095+/* ---------------------------------------------------------------------- */
8096+
8097+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
8098+int __init au_sysrq_init(void);
8099+void au_sysrq_fin(void);
8100+
8101+#ifdef CONFIG_HW_CONSOLE
8102+#define au_dbg_blocked() do { \
8103+ WARN_ON(1); \
0c5527e5 8104+ handle_sysrq('w'); \
1facf9fc 8105+} while (0)
8106+#else
4a4d8108 8107+AuStubVoid(au_dbg_blocked, void)
1facf9fc 8108+#endif
8109+
8110+#else
4a4d8108
AM
8111+AuStubInt0(__init au_sysrq_init, void)
8112+AuStubVoid(au_sysrq_fin, void)
8113+AuStubVoid(au_dbg_blocked, void)
1facf9fc 8114+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
8115+
8116+#endif /* __KERNEL__ */
8117+#endif /* __AUFS_DEBUG_H__ */
7f207e10 8118diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
eca34b5c
AM
8119--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
8120+++ linux/fs/aufs/dentry.c 2019-07-11 15:42:14.462237786 +0200
eca801bf 8121@@ -0,0 +1,1154 @@
cd7a4cd9 8122+// SPDX-License-Identifier: GPL-2.0
1facf9fc 8123+/*
ba1aed25 8124+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 8125+ *
8126+ * This program, aufs is free software; you can redistribute it and/or modify
8127+ * it under the terms of the GNU General Public License as published by
8128+ * the Free Software Foundation; either version 2 of the License, or
8129+ * (at your option) any later version.
dece6358
AM
8130+ *
8131+ * This program is distributed in the hope that it will be useful,
8132+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8133+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8134+ * GNU General Public License for more details.
8135+ *
8136+ * You should have received a copy of the GNU General Public License
523b37e3 8137+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 8138+ */
8139+
8140+/*
8141+ * lookup and dentry operations
8142+ */
8143+
eca801bf 8144+#include <linux/iversion.h>
dece6358 8145+#include <linux/namei.h>
1facf9fc 8146+#include "aufs.h"
8147+
1facf9fc 8148+/*
8149+ * returns positive/negative dentry, NULL or an error.
8150+ * NULL means whiteout-ed or not-found.
8151+ */
8152+static struct dentry*
8153+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
8b6a4947 8154+ aufs_bindex_t bindex, struct au_do_lookup_args *args)
1facf9fc 8155+{
8156+ struct dentry *h_dentry;
2000de60 8157+ struct inode *h_inode;
1facf9fc 8158+ struct au_branch *br;
8159+ int wh_found, opq;
8160+ unsigned char wh_able;
8161+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
076b876e
AM
8162+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags,
8163+ IGNORE_PERM);
1facf9fc 8164+
1facf9fc 8165+ wh_found = 0;
8166+ br = au_sbr(dentry->d_sb, bindex);
8167+ wh_able = !!au_br_whable(br->br_perm);
8168+ if (wh_able)
8b6a4947 8169+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm);
1facf9fc 8170+ h_dentry = ERR_PTR(wh_found);
8171+ if (!wh_found)
8172+ goto real_lookup;
8173+ if (unlikely(wh_found < 0))
8174+ goto out;
8175+
8176+ /* We found a whiteout */
5afbbe0d 8177+ /* au_set_dbbot(dentry, bindex); */
1facf9fc 8178+ au_set_dbwh(dentry, bindex);
8179+ if (!allow_neg)
8180+ return NULL; /* success */
8181+
4f0767ce 8182+real_lookup:
076b876e 8183+ if (!ignore_perm)
8b6a4947 8184+ h_dentry = vfsub_lkup_one(args->name, h_parent);
076b876e 8185+ else
8b6a4947 8186+ h_dentry = au_sio_lkup_one(args->name, h_parent);
2000de60
JR
8187+ if (IS_ERR(h_dentry)) {
8188+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG
8189+ && !allow_neg)
8190+ h_dentry = NULL;
1facf9fc 8191+ goto out;
2000de60 8192+ }
1facf9fc 8193+
5527c038
JR
8194+ h_inode = d_inode(h_dentry);
8195+ if (d_is_negative(h_dentry)) {
1facf9fc 8196+ if (!allow_neg)
8197+ goto out_neg;
8198+ } else if (wh_found
8199+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
8200+ goto out_neg;
8b6a4947
AM
8201+ else if (au_ftest_lkup(args->flags, DIRREN)
8202+ /* && h_inode */
8203+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) {
8204+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry,
8205+ (unsigned long long)h_inode->i_ino);
8206+ goto out_neg;
8207+ }
1facf9fc 8208+
5afbbe0d
AM
8209+ if (au_dbbot(dentry) <= bindex)
8210+ au_set_dbbot(dentry, bindex);
8211+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
8212+ au_set_dbtop(dentry, bindex);
1facf9fc 8213+ au_set_h_dptr(dentry, bindex, h_dentry);
8214+
2000de60
JR
8215+ if (!d_is_dir(h_dentry)
8216+ || !wh_able
5527c038 8217+ || (d_really_is_positive(dentry) && !d_is_dir(dentry)))
1facf9fc 8218+ goto out; /* success */
8219+
be118d29 8220+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
076b876e 8221+ opq = au_diropq_test(h_dentry);
3c1bdaff 8222+ inode_unlock_shared(h_inode);
1facf9fc 8223+ if (opq > 0)
8224+ au_set_dbdiropq(dentry, bindex);
8225+ else if (unlikely(opq < 0)) {
8226+ au_set_h_dptr(dentry, bindex, NULL);
8227+ h_dentry = ERR_PTR(opq);
8228+ }
8229+ goto out;
8230+
4f0767ce 8231+out_neg:
1facf9fc 8232+ dput(h_dentry);
8233+ h_dentry = NULL;
4f0767ce 8234+out:
1facf9fc 8235+ return h_dentry;
8236+}
8237+
dece6358
AM
8238+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
8239+{
8240+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
8241+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
8242+ return -EPERM;
8243+ return 0;
8244+}
8245+
1facf9fc 8246+/*
8247+ * returns the number of lower positive dentries,
8248+ * otherwise an error.
8249+ * can be called at unlinking with @type is zero.
8250+ */
5afbbe0d
AM
8251+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
8252+ unsigned int flags)
1facf9fc 8253+{
8254+ int npositive, err;
8255+ aufs_bindex_t bindex, btail, bdiropq;
8b6a4947 8256+ unsigned char isdir, dirperm1, dirren;
1facf9fc 8257+ struct au_do_lookup_args args = {
8b6a4947
AM
8258+ .flags = flags,
8259+ .name = &dentry->d_name
1facf9fc 8260+ };
1facf9fc 8261+ struct dentry *parent;
076b876e 8262+ struct super_block *sb;
1facf9fc 8263+
076b876e 8264+ sb = dentry->d_sb;
8b6a4947 8265+ err = au_test_shwh(sb, args.name);
dece6358 8266+ if (unlikely(err))
1facf9fc 8267+ goto out;
8268+
8b6a4947 8269+ err = au_wh_name_alloc(&args.whname, args.name);
1facf9fc 8270+ if (unlikely(err))
8271+ goto out;
8272+
2000de60 8273+ isdir = !!d_is_dir(dentry);
076b876e 8274+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1);
8b6a4947
AM
8275+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
8276+ if (dirren)
8277+ au_fset_lkup(args.flags, DIRREN);
1facf9fc 8278+
8279+ npositive = 0;
4a4d8108 8280+ parent = dget_parent(dentry);
1facf9fc 8281+ btail = au_dbtaildir(parent);
5afbbe0d 8282+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8283+ struct dentry *h_parent, *h_dentry;
8284+ struct inode *h_inode, *h_dir;
8b6a4947 8285+ struct au_branch *br;
1facf9fc 8286+
8287+ h_dentry = au_h_dptr(dentry, bindex);
8288+ if (h_dentry) {
5527c038 8289+ if (d_is_positive(h_dentry))
1facf9fc 8290+ npositive++;
5afbbe0d 8291+ break;
1facf9fc 8292+ }
8293+ h_parent = au_h_dptr(parent, bindex);
2000de60 8294+ if (!h_parent || !d_is_dir(h_parent))
1facf9fc 8295+ continue;
8296+
8b6a4947
AM
8297+ if (dirren) {
8298+ /* if the inum matches, then use the prepared name */
8299+ err = au_dr_lkup_name(&args, bindex);
8300+ if (unlikely(err))
8301+ goto out_parent;
8302+ }
8303+
5527c038 8304+ h_dir = d_inode(h_parent);
be118d29 8305+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947 8306+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args);
3c1bdaff 8307+ inode_unlock_shared(h_dir);
1facf9fc 8308+ err = PTR_ERR(h_dentry);
8309+ if (IS_ERR(h_dentry))
4a4d8108 8310+ goto out_parent;
2000de60
JR
8311+ if (h_dentry)
8312+ au_fclr_lkup(args.flags, ALLOW_NEG);
076b876e
AM
8313+ if (dirperm1)
8314+ au_fset_lkup(args.flags, IGNORE_PERM);
1facf9fc 8315+
79b8bda9 8316+ if (au_dbwh(dentry) == bindex)
1facf9fc 8317+ break;
8318+ if (!h_dentry)
8319+ continue;
5527c038 8320+ if (d_is_negative(h_dentry))
1facf9fc 8321+ continue;
5527c038 8322+ h_inode = d_inode(h_dentry);
1facf9fc 8323+ npositive++;
8324+ if (!args.type)
8325+ args.type = h_inode->i_mode & S_IFMT;
8326+ if (args.type != S_IFDIR)
8327+ break;
8328+ else if (isdir) {
8329+ /* the type of lower may be different */
8330+ bdiropq = au_dbdiropq(dentry);
8331+ if (bdiropq >= 0 && bdiropq <= bindex)
8332+ break;
8333+ }
8b6a4947
AM
8334+ br = au_sbr(sb, bindex);
8335+ if (dirren
8336+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino,
8337+ /*add_ent*/NULL)) {
8338+ /* prepare next name to lookup */
8339+ err = au_dr_lkup(&args, dentry, bindex);
8340+ if (unlikely(err))
8341+ goto out_parent;
8342+ }
1facf9fc 8343+ }
8344+
8345+ if (npositive) {
8346+ AuLabel(positive);
5afbbe0d 8347+ au_update_dbtop(dentry);
1facf9fc 8348+ }
8349+ err = npositive;
076b876e 8350+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE)
5afbbe0d 8351+ && au_dbtop(dentry) < 0)) {
1facf9fc 8352+ err = -EIO;
523b37e3
AM
8353+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n",
8354+ dentry, err);
027c5e7a 8355+ }
1facf9fc 8356+
4f0767ce 8357+out_parent:
4a4d8108 8358+ dput(parent);
9f237c51 8359+ au_kfree_try_rcu(args.whname.name);
8b6a4947
AM
8360+ if (dirren)
8361+ au_dr_lkup_fin(&args);
4f0767ce 8362+out:
1facf9fc 8363+ return err;
8364+}
8365+
076b876e 8366+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent)
1facf9fc 8367+{
8368+ struct dentry *dentry;
8369+ int wkq_err;
8370+
5527c038 8371+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC))
b4510431 8372+ dentry = vfsub_lkup_one(name, parent);
1facf9fc 8373+ else {
b4510431
AM
8374+ struct vfsub_lkup_one_args args = {
8375+ .errp = &dentry,
8376+ .name = name,
8377+ .parent = parent
1facf9fc 8378+ };
8379+
b4510431 8380+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
1facf9fc 8381+ if (unlikely(wkq_err))
8382+ dentry = ERR_PTR(wkq_err);
8383+ }
8384+
8385+ return dentry;
8386+}
8387+
8388+/*
8389+ * lookup @dentry on @bindex which should be negative.
8390+ */
86dc4139 8391+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
1facf9fc 8392+{
8393+ int err;
8394+ struct dentry *parent, *h_parent, *h_dentry;
86dc4139 8395+ struct au_branch *br;
1facf9fc 8396+
1facf9fc 8397+ parent = dget_parent(dentry);
8398+ h_parent = au_h_dptr(parent, bindex);
86dc4139
AM
8399+ br = au_sbr(dentry->d_sb, bindex);
8400+ if (wh)
8401+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
8402+ else
076b876e 8403+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent);
1facf9fc 8404+ err = PTR_ERR(h_dentry);
8405+ if (IS_ERR(h_dentry))
8406+ goto out;
5527c038 8407+ if (unlikely(d_is_positive(h_dentry))) {
1facf9fc 8408+ err = -EIO;
523b37e3 8409+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex);
1facf9fc 8410+ dput(h_dentry);
8411+ goto out;
8412+ }
8413+
4a4d8108 8414+ err = 0;
5afbbe0d
AM
8415+ if (bindex < au_dbtop(dentry))
8416+ au_set_dbtop(dentry, bindex);
8417+ if (au_dbbot(dentry) < bindex)
8418+ au_set_dbbot(dentry, bindex);
1facf9fc 8419+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 8420+
4f0767ce 8421+out:
1facf9fc 8422+ dput(parent);
8423+ return err;
8424+}
8425+
8426+/* ---------------------------------------------------------------------- */
8427+
8428+/* subset of struct inode */
8429+struct au_iattr {
8430+ unsigned long i_ino;
8431+ /* unsigned int i_nlink; */
0c3ec466
AM
8432+ kuid_t i_uid;
8433+ kgid_t i_gid;
1facf9fc 8434+ u64 i_version;
8435+/*
8436+ loff_t i_size;
8437+ blkcnt_t i_blocks;
8438+*/
8439+ umode_t i_mode;
8440+};
8441+
8442+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
8443+{
8444+ ia->i_ino = h_inode->i_ino;
8445+ /* ia->i_nlink = h_inode->i_nlink; */
8446+ ia->i_uid = h_inode->i_uid;
8447+ ia->i_gid = h_inode->i_gid;
be118d29 8448+ ia->i_version = inode_query_iversion(h_inode);
1facf9fc 8449+/*
8450+ ia->i_size = h_inode->i_size;
8451+ ia->i_blocks = h_inode->i_blocks;
8452+*/
8453+ ia->i_mode = (h_inode->i_mode & S_IFMT);
8454+}
8455+
8456+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
8457+{
8458+ return ia->i_ino != h_inode->i_ino
8459+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466 8460+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 8461+ || !gid_eq(ia->i_gid, h_inode->i_gid)
be118d29 8462+ || !inode_eq_iversion(h_inode, ia->i_version)
1facf9fc 8463+/*
8464+ || ia->i_size != h_inode->i_size
8465+ || ia->i_blocks != h_inode->i_blocks
8466+*/
8467+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
8468+}
8469+
8470+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
8471+ struct au_branch *br)
8472+{
8473+ int err;
8474+ struct au_iattr ia;
8475+ struct inode *h_inode;
8476+ struct dentry *h_d;
8477+ struct super_block *h_sb;
8478+
8479+ err = 0;
8480+ memset(&ia, -1, sizeof(ia));
8481+ h_sb = h_dentry->d_sb;
5527c038
JR
8482+ h_inode = NULL;
8483+ if (d_is_positive(h_dentry)) {
8484+ h_inode = d_inode(h_dentry);
1facf9fc 8485+ au_iattr_save(&ia, h_inode);
5527c038 8486+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
1facf9fc 8487+ /* nfs d_revalidate may return 0 for negative dentry */
8488+ /* fuse d_revalidate always return 0 for negative dentry */
8489+ goto out;
8490+
8491+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
b4510431 8492+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
1facf9fc 8493+ err = PTR_ERR(h_d);
8494+ if (IS_ERR(h_d))
8495+ goto out;
8496+
8497+ err = 0;
8498+ if (unlikely(h_d != h_dentry
5527c038 8499+ || d_inode(h_d) != h_inode
1facf9fc 8500+ || (h_inode && au_iattr_test(&ia, h_inode))))
8501+ err = au_busy_or_stale();
8502+ dput(h_d);
8503+
4f0767ce 8504+out:
1facf9fc 8505+ AuTraceErr(err);
8506+ return err;
8507+}
8508+
8509+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
8510+ struct dentry *h_parent, struct au_branch *br)
8511+{
8512+ int err;
8513+
8514+ err = 0;
027c5e7a
AM
8515+ if (udba == AuOpt_UDBA_REVAL
8516+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 8517+ IMustLock(h_dir);
5527c038 8518+ err = (d_inode(h_dentry->d_parent) != h_dir);
027c5e7a 8519+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 8520+ err = au_h_verify_dentry(h_dentry, h_parent, br);
8521+
8522+ return err;
8523+}
8524+
8525+/* ---------------------------------------------------------------------- */
8526+
027c5e7a 8527+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 8528+{
027c5e7a 8529+ int err;
5afbbe0d 8530+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq;
027c5e7a
AM
8531+ struct au_hdentry tmp, *p, *q;
8532+ struct au_dinfo *dinfo;
8533+ struct super_block *sb;
1facf9fc 8534+
027c5e7a 8535+ DiMustWriteLock(dentry);
1308ab2a 8536+
027c5e7a
AM
8537+ sb = dentry->d_sb;
8538+ dinfo = au_di(dentry);
5afbbe0d 8539+ bbot = dinfo->di_bbot;
1facf9fc 8540+ bwh = dinfo->di_bwh;
8541+ bdiropq = dinfo->di_bdiropq;
5afbbe0d
AM
8542+ bindex = dinfo->di_btop;
8543+ p = au_hdentry(dinfo, bindex);
8544+ for (; bindex <= bbot; bindex++, p++) {
027c5e7a 8545+ if (!p->hd_dentry)
1facf9fc 8546+ continue;
8547+
027c5e7a
AM
8548+ new_bindex = au_br_index(sb, p->hd_id);
8549+ if (new_bindex == bindex)
1facf9fc 8550+ continue;
1facf9fc 8551+
1facf9fc 8552+ if (dinfo->di_bwh == bindex)
8553+ bwh = new_bindex;
8554+ if (dinfo->di_bdiropq == bindex)
8555+ bdiropq = new_bindex;
8556+ if (new_bindex < 0) {
8557+ au_hdput(p);
8558+ p->hd_dentry = NULL;
8559+ continue;
8560+ }
8561+
8562+ /* swap two lower dentries, and loop again */
5afbbe0d 8563+ q = au_hdentry(dinfo, new_bindex);
1facf9fc 8564+ tmp = *q;
8565+ *q = *p;
8566+ *p = tmp;
8567+ if (tmp.hd_dentry) {
8568+ bindex--;
8569+ p--;
8570+ }
8571+ }
8572+
1facf9fc 8573+ dinfo->di_bwh = -1;
5afbbe0d 8574+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh))
1facf9fc 8575+ dinfo->di_bwh = bwh;
8576+
8577+ dinfo->di_bdiropq = -1;
8578+ if (bdiropq >= 0
5afbbe0d 8579+ && bdiropq <= au_sbbot(sb)
1facf9fc 8580+ && au_sbr_whable(sb, bdiropq))
8581+ dinfo->di_bdiropq = bdiropq;
8582+
027c5e7a 8583+ err = -EIO;
5afbbe0d
AM
8584+ dinfo->di_btop = -1;
8585+ dinfo->di_bbot = -1;
8586+ bbot = au_dbbot(parent);
8587+ bindex = 0;
8588+ p = au_hdentry(dinfo, bindex);
8589+ for (; bindex <= bbot; bindex++, p++)
1facf9fc 8590+ if (p->hd_dentry) {
5afbbe0d 8591+ dinfo->di_btop = bindex;
1facf9fc 8592+ break;
8593+ }
8594+
5afbbe0d
AM
8595+ if (dinfo->di_btop >= 0) {
8596+ bindex = bbot;
8597+ p = au_hdentry(dinfo, bindex);
8598+ for (; bindex >= 0; bindex--, p--)
027c5e7a 8599+ if (p->hd_dentry) {
5afbbe0d 8600+ dinfo->di_bbot = bindex;
027c5e7a
AM
8601+ err = 0;
8602+ break;
8603+ }
8604+ }
8605+
8606+ return err;
1facf9fc 8607+}
8608+
027c5e7a 8609+static void au_do_hide(struct dentry *dentry)
1facf9fc 8610+{
027c5e7a 8611+ struct inode *inode;
1facf9fc 8612+
5527c038
JR
8613+ if (d_really_is_positive(dentry)) {
8614+ inode = d_inode(dentry);
8615+ if (!d_is_dir(dentry)) {
027c5e7a
AM
8616+ if (inode->i_nlink && !d_unhashed(dentry))
8617+ drop_nlink(inode);
8618+ } else {
8619+ clear_nlink(inode);
8620+ /* stop next lookup */
8621+ inode->i_flags |= S_DEAD;
8622+ }
8623+ smp_mb(); /* necessary? */
8624+ }
8625+ d_drop(dentry);
8626+}
1308ab2a 8627+
027c5e7a
AM
8628+static int au_hide_children(struct dentry *parent)
8629+{
8630+ int err, i, j, ndentry;
8631+ struct au_dcsub_pages dpages;
8632+ struct au_dpage *dpage;
8633+ struct dentry *dentry;
1facf9fc 8634+
027c5e7a 8635+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 8636+ if (unlikely(err))
8637+ goto out;
027c5e7a
AM
8638+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
8639+ if (unlikely(err))
8640+ goto out_dpages;
1facf9fc 8641+
027c5e7a
AM
8642+ /* in reverse order */
8643+ for (i = dpages.ndpage - 1; i >= 0; i--) {
8644+ dpage = dpages.dpages + i;
8645+ ndentry = dpage->ndentry;
8646+ for (j = ndentry - 1; j >= 0; j--) {
8647+ dentry = dpage->dentries[j];
8648+ if (dentry != parent)
8649+ au_do_hide(dentry);
8650+ }
8651+ }
1facf9fc 8652+
027c5e7a
AM
8653+out_dpages:
8654+ au_dpages_free(&dpages);
4f0767ce 8655+out:
027c5e7a 8656+ return err;
1facf9fc 8657+}
8658+
027c5e7a 8659+static void au_hide(struct dentry *dentry)
1facf9fc 8660+{
027c5e7a 8661+ int err;
1facf9fc 8662+
027c5e7a 8663+ AuDbgDentry(dentry);
2000de60 8664+ if (d_is_dir(dentry)) {
027c5e7a
AM
8665+ /* shrink_dcache_parent(dentry); */
8666+ err = au_hide_children(dentry);
8667+ if (unlikely(err))
523b37e3
AM
8668+ AuIOErr("%pd, failed hiding children, ignored %d\n",
8669+ dentry, err);
027c5e7a
AM
8670+ }
8671+ au_do_hide(dentry);
8672+}
1facf9fc 8673+
027c5e7a
AM
8674+/*
8675+ * By adding a dirty branch, a cached dentry may be affected in various ways.
8676+ *
8677+ * a dirty branch is added
8678+ * - on the top of layers
8679+ * - in the middle of layers
8680+ * - to the bottom of layers
8681+ *
8682+ * on the added branch there exists
8683+ * - a whiteout
8684+ * - a diropq
8685+ * - a same named entry
8686+ * + exist
8687+ * * negative --> positive
8688+ * * positive --> positive
8689+ * - type is unchanged
8690+ * - type is changed
8691+ * + doesn't exist
8692+ * * negative --> negative
8693+ * * positive --> negative (rejected by au_br_del() for non-dir case)
8694+ * - none
8695+ */
8696+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
8697+ struct au_dinfo *tmp)
8698+{
8699+ int err;
5afbbe0d 8700+ aufs_bindex_t bindex, bbot;
027c5e7a
AM
8701+ struct {
8702+ struct dentry *dentry;
8703+ struct inode *inode;
8704+ mode_t mode;
be52b249
AM
8705+ } orig_h, tmp_h = {
8706+ .dentry = NULL
8707+ };
027c5e7a
AM
8708+ struct au_hdentry *hd;
8709+ struct inode *inode, *h_inode;
8710+ struct dentry *h_dentry;
8711+
8712+ err = 0;
5afbbe0d 8713+ AuDebugOn(dinfo->di_btop < 0);
027c5e7a 8714+ orig_h.mode = 0;
5afbbe0d 8715+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry;
5527c038
JR
8716+ orig_h.inode = NULL;
8717+ if (d_is_positive(orig_h.dentry)) {
8718+ orig_h.inode = d_inode(orig_h.dentry);
027c5e7a 8719+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5527c038 8720+ }
5afbbe0d
AM
8721+ if (tmp->di_btop >= 0) {
8722+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry;
5527c038
JR
8723+ if (d_is_positive(tmp_h.dentry)) {
8724+ tmp_h.inode = d_inode(tmp_h.dentry);
027c5e7a 8725+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5527c038 8726+ }
027c5e7a
AM
8727+ }
8728+
5527c038
JR
8729+ inode = NULL;
8730+ if (d_really_is_positive(dentry))
8731+ inode = d_inode(dentry);
027c5e7a 8732+ if (!orig_h.inode) {
acd2b654 8733+ AuDbg("negative originally\n");
027c5e7a
AM
8734+ if (inode) {
8735+ au_hide(dentry);
8736+ goto out;
8737+ }
8738+ AuDebugOn(inode);
5afbbe0d 8739+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
027c5e7a
AM
8740+ AuDebugOn(dinfo->di_bdiropq != -1);
8741+
8742+ if (!tmp_h.inode) {
8743+ AuDbg("negative --> negative\n");
8744+ /* should have only one negative lower */
5afbbe0d
AM
8745+ if (tmp->di_btop >= 0
8746+ && tmp->di_btop < dinfo->di_btop) {
8747+ AuDebugOn(tmp->di_btop != tmp->di_bbot);
8748+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
8749+ au_set_h_dptr(dentry, dinfo->di_btop, NULL);
027c5e7a 8750+ au_di_cp(dinfo, tmp);
5afbbe0d
AM
8751+ hd = au_hdentry(tmp, tmp->di_btop);
8752+ au_set_h_dptr(dentry, tmp->di_btop,
027c5e7a
AM
8753+ dget(hd->hd_dentry));
8754+ }
8755+ au_dbg_verify_dinode(dentry);
8756+ } else {
8757+ AuDbg("negative --> positive\n");
8758+ /*
8759+ * similar to the behaviour of creating with bypassing
8760+ * aufs.
8761+ * unhash it in order to force an error in the
8762+ * succeeding create operation.
8763+ * we should not set S_DEAD here.
8764+ */
8765+ d_drop(dentry);
8766+ /* au_di_swap(tmp, dinfo); */
8767+ au_dbg_verify_dinode(dentry);
8768+ }
8769+ } else {
8770+ AuDbg("positive originally\n");
8771+ /* inode may be NULL */
8772+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
8773+ if (!tmp_h.inode) {
8774+ AuDbg("positive --> negative\n");
8775+ /* or bypassing aufs */
8776+ au_hide(dentry);
5afbbe0d 8777+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop)
027c5e7a
AM
8778+ dinfo->di_bwh = tmp->di_bwh;
8779+ if (inode)
8780+ err = au_refresh_hinode_self(inode);
8781+ au_dbg_verify_dinode(dentry);
8782+ } else if (orig_h.mode == tmp_h.mode) {
8783+ AuDbg("positive --> positive, same type\n");
8784+ if (!S_ISDIR(orig_h.mode)
5afbbe0d 8785+ && dinfo->di_btop > tmp->di_btop) {
027c5e7a
AM
8786+ /*
8787+ * similar to the behaviour of removing and
8788+ * creating.
8789+ */
8790+ au_hide(dentry);
8791+ if (inode)
8792+ err = au_refresh_hinode_self(inode);
8793+ au_dbg_verify_dinode(dentry);
8794+ } else {
8795+ /* fill empty slots */
5afbbe0d
AM
8796+ if (dinfo->di_btop > tmp->di_btop)
8797+ dinfo->di_btop = tmp->di_btop;
8798+ if (dinfo->di_bbot < tmp->di_bbot)
8799+ dinfo->di_bbot = tmp->di_bbot;
027c5e7a
AM
8800+ dinfo->di_bwh = tmp->di_bwh;
8801+ dinfo->di_bdiropq = tmp->di_bdiropq;
5afbbe0d
AM
8802+ bbot = dinfo->di_bbot;
8803+ bindex = tmp->di_btop;
8804+ hd = au_hdentry(tmp, bindex);
8805+ for (; bindex <= bbot; bindex++, hd++) {
027c5e7a
AM
8806+ if (au_h_dptr(dentry, bindex))
8807+ continue;
5afbbe0d 8808+ h_dentry = hd->hd_dentry;
027c5e7a
AM
8809+ if (!h_dentry)
8810+ continue;
5527c038
JR
8811+ AuDebugOn(d_is_negative(h_dentry));
8812+ h_inode = d_inode(h_dentry);
027c5e7a
AM
8813+ AuDebugOn(orig_h.mode
8814+ != (h_inode->i_mode
8815+ & S_IFMT));
8816+ au_set_h_dptr(dentry, bindex,
8817+ dget(h_dentry));
8818+ }
5afbbe0d
AM
8819+ if (inode)
8820+ err = au_refresh_hinode(inode, dentry);
027c5e7a
AM
8821+ au_dbg_verify_dinode(dentry);
8822+ }
8823+ } else {
8824+ AuDbg("positive --> positive, different type\n");
8825+ /* similar to the behaviour of removing and creating */
8826+ au_hide(dentry);
8827+ if (inode)
8828+ err = au_refresh_hinode_self(inode);
8829+ au_dbg_verify_dinode(dentry);
8830+ }
8831+ }
8832+
8833+out:
8834+ return err;
8835+}
8836+
79b8bda9
AM
8837+void au_refresh_dop(struct dentry *dentry, int force_reval)
8838+{
8839+ const struct dentry_operations *dop
8840+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op;
8841+ static const unsigned int mask
8842+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE;
8843+
8844+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags));
8845+
8846+ if (dentry->d_op == dop)
8847+ return;
8848+
8849+ AuDbg("%pd\n", dentry);
8850+ spin_lock(&dentry->d_lock);
8851+ if (dop == &aufs_dop)
8852+ dentry->d_flags |= mask;
8853+ else
8854+ dentry->d_flags &= ~mask;
8855+ dentry->d_op = dop;
8856+ spin_unlock(&dentry->d_lock);
8857+}
8858+
027c5e7a
AM
8859+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
8860+{
e2f27e51 8861+ int err, ebrange, nbr;
027c5e7a
AM
8862+ unsigned int sigen;
8863+ struct au_dinfo *dinfo, *tmp;
8864+ struct super_block *sb;
8865+ struct inode *inode;
8866+
8867+ DiMustWriteLock(dentry);
8868+ AuDebugOn(IS_ROOT(dentry));
5527c038 8869+ AuDebugOn(d_really_is_negative(parent));
027c5e7a
AM
8870+
8871+ sb = dentry->d_sb;
027c5e7a
AM
8872+ sigen = au_sigen(sb);
8873+ err = au_digen_test(parent, sigen);
8874+ if (unlikely(err))
8875+ goto out;
8876+
e2f27e51 8877+ nbr = au_sbbot(sb) + 1;
027c5e7a 8878+ dinfo = au_di(dentry);
e2f27e51 8879+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0);
027c5e7a
AM
8880+ if (unlikely(err))
8881+ goto out;
8882+ ebrange = au_dbrange_test(dentry);
8883+ if (!ebrange)
8884+ ebrange = au_do_refresh_hdentry(dentry, parent);
8885+
38d290e6 8886+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) {
5afbbe0d 8887+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0);
5527c038
JR
8888+ if (d_really_is_positive(dentry)) {
8889+ inode = d_inode(dentry);
027c5e7a 8890+ err = au_refresh_hinode_self(inode);
5527c038 8891+ }
027c5e7a
AM
8892+ au_dbg_verify_dinode(dentry);
8893+ if (!err)
8894+ goto out_dgen; /* success */
8895+ goto out;
8896+ }
8897+
8898+ /* temporary dinfo */
8899+ AuDbgDentry(dentry);
8900+ err = -ENOMEM;
8901+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
8902+ if (unlikely(!tmp))
8903+ goto out;
8904+ au_di_swap(tmp, dinfo);
8905+ /* returns the number of positive dentries */
8906+ /*
8907+ * if current working dir is removed, it returns an error.
8908+ * but the dentry is legal.
8909+ */
5afbbe0d 8910+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
027c5e7a
AM
8911+ AuDbgDentry(dentry);
8912+ au_di_swap(tmp, dinfo);
8913+ if (err == -ENOENT)
8914+ err = 0;
8915+ if (err >= 0) {
8916+ /* compare/refresh by dinfo */
8917+ AuDbgDentry(dentry);
8918+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
8919+ au_dbg_verify_dinode(dentry);
8920+ AuTraceErr(err);
8921+ }
e2f27e51 8922+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */
027c5e7a
AM
8923+ au_rw_write_unlock(&tmp->di_rwsem);
8924+ au_di_free(tmp);
8925+ if (unlikely(err))
8926+ goto out;
8927+
8928+out_dgen:
8929+ au_update_digen(dentry);
8930+out:
8931+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
523b37e3 8932+ AuIOErr("failed refreshing %pd, %d\n", dentry, err);
027c5e7a
AM
8933+ AuDbgDentry(dentry);
8934+ }
8935+ AuTraceErr(err);
8936+ return err;
8937+}
8938+
b4510431
AM
8939+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
8940+ struct dentry *dentry, aufs_bindex_t bindex)
027c5e7a
AM
8941+{
8942+ int err, valid;
027c5e7a
AM
8943+
8944+ err = 0;
8945+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
8946+ goto out;
027c5e7a
AM
8947+
8948+ AuDbg("b%d\n", bindex);
b4510431
AM
8949+ /*
8950+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
8951+ * due to whiteout and branch permission.
8952+ */
8953+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
8954+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
8955+ /* it may return tri-state */
8956+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags);
1facf9fc 8957+
8958+ if (unlikely(valid < 0))
8959+ err = valid;
8960+ else if (!valid)
8961+ err = -EINVAL;
8962+
4f0767ce 8963+out:
1facf9fc 8964+ AuTraceErr(err);
8965+ return err;
8966+}
8967+
8968+/* todo: remove this */
8969+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
8b6a4947 8970+ unsigned int flags, int do_udba, int dirren)
1facf9fc 8971+{
8972+ int err;
8973+ umode_t mode, h_mode;
5afbbe0d 8974+ aufs_bindex_t bindex, btail, btop, ibs, ibe;
38d290e6 8975+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile;
4a4d8108 8976+ struct inode *h_inode, *h_cached_inode;
1facf9fc 8977+ struct dentry *h_dentry;
8978+ struct qstr *name, *h_name;
8979+
8980+ err = 0;
8981+ plus = 0;
8982+ mode = 0;
1facf9fc 8983+ ibs = -1;
8984+ ibe = -1;
8985+ unhashed = !!d_unhashed(dentry);
8986+ is_root = !!IS_ROOT(dentry);
8987+ name = &dentry->d_name;
38d290e6 8988+ tmpfile = au_di(dentry)->di_tmpfile;
1facf9fc 8989+
8990+ /*
7f207e10
AM
8991+ * Theoretically, REVAL test should be unnecessary in case of
8992+ * {FS,I}NOTIFY.
8993+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 8994+ * IN_ATTRIB for atime/nlink/pageio
1facf9fc 8995+ * Let's do REVAL test too.
8996+ */
8997+ if (do_udba && inode) {
8998+ mode = (inode->i_mode & S_IFMT);
8999+ plus = (inode->i_nlink > 0);
5afbbe0d
AM
9000+ ibs = au_ibtop(inode);
9001+ ibe = au_ibbot(inode);
1facf9fc 9002+ }
9003+
5afbbe0d
AM
9004+ btop = au_dbtop(dentry);
9005+ btail = btop;
1facf9fc 9006+ if (inode && S_ISDIR(inode->i_mode))
9007+ btail = au_dbtaildir(dentry);
5afbbe0d 9008+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 9009+ h_dentry = au_h_dptr(dentry, bindex);
9010+ if (!h_dentry)
9011+ continue;
9012+
523b37e3
AM
9013+ AuDbg("b%d, %pd\n", bindex, h_dentry);
9014+ h_nfs = !!au_test_nfs(h_dentry->d_sb);
027c5e7a 9015+ spin_lock(&h_dentry->d_lock);
1facf9fc 9016+ h_name = &h_dentry->d_name;
9017+ if (unlikely(do_udba
9018+ && !is_root
523b37e3
AM
9019+ && ((!h_nfs
9020+ && (unhashed != !!d_unhashed(h_dentry)
8b6a4947 9021+ || (!tmpfile && !dirren
38d290e6
JR
9022+ && !au_qstreq(name, h_name))
9023+ ))
523b37e3
AM
9024+ || (h_nfs
9025+ && !(flags & LOOKUP_OPEN)
9026+ && (h_dentry->d_flags
9027+ & DCACHE_NFSFS_RENAMED)))
1facf9fc 9028+ )) {
38d290e6
JR
9029+ int h_unhashed;
9030+
9031+ h_unhashed = d_unhashed(h_dentry);
027c5e7a 9032+ spin_unlock(&h_dentry->d_lock);
38d290e6
JR
9033+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n",
9034+ unhashed, h_unhashed, dentry, h_dentry);
1facf9fc 9035+ goto err;
9036+ }
027c5e7a 9037+ spin_unlock(&h_dentry->d_lock);
1facf9fc 9038+
b4510431 9039+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex);
1facf9fc 9040+ if (unlikely(err))
9041+ /* do not goto err, to keep the errno */
9042+ break;
9043+
9044+ /* todo: plink too? */
9045+ if (!do_udba)
9046+ continue;
9047+
9048+ /* UDBA tests */
5527c038 9049+ if (unlikely(!!inode != d_is_positive(h_dentry)))
1facf9fc 9050+ goto err;
9051+
5527c038
JR
9052+ h_inode = NULL;
9053+ if (d_is_positive(h_dentry))
9054+ h_inode = d_inode(h_dentry);
1facf9fc 9055+ h_plus = plus;
9056+ h_mode = mode;
9057+ h_cached_inode = h_inode;
9058+ if (h_inode) {
9059+ h_mode = (h_inode->i_mode & S_IFMT);
9060+ h_plus = (h_inode->i_nlink > 0);
9061+ }
9062+ if (inode && ibs <= bindex && bindex <= ibe)
9063+ h_cached_inode = au_h_iptr(inode, bindex);
9064+
523b37e3 9065+ if (!h_nfs) {
38d290e6 9066+ if (unlikely(plus != h_plus && !tmpfile))
523b37e3
AM
9067+ goto err;
9068+ } else {
9069+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED)
9070+ && !is_root
9071+ && !IS_ROOT(h_dentry)
9072+ && unhashed != d_unhashed(h_dentry)))
9073+ goto err;
9074+ }
9075+ if (unlikely(mode != h_mode
1facf9fc 9076+ || h_cached_inode != h_inode))
9077+ goto err;
9078+ continue;
9079+
f6b6e03d 9080+err:
1facf9fc 9081+ err = -EINVAL;
9082+ break;
9083+ }
9084+
523b37e3 9085+ AuTraceErr(err);
1facf9fc 9086+ return err;
9087+}
9088+
027c5e7a 9089+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 9090+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
9091+{
9092+ int err;
9093+ struct dentry *parent;
1facf9fc 9094+
027c5e7a 9095+ if (!au_digen_test(dentry, sigen))
1facf9fc 9096+ return 0;
9097+
9098+ parent = dget_parent(dentry);
9099+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 9100+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 9101+ au_dbg_verify_gen(parent, sigen);
027c5e7a 9102+ err = au_refresh_dentry(dentry, parent);
1facf9fc 9103+ di_read_unlock(parent, AuLock_IR);
9104+ dput(parent);
027c5e7a 9105+ AuTraceErr(err);
1facf9fc 9106+ return err;
9107+}
9108+
9109+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
9110+{
9111+ int err;
9112+ struct dentry *d, *parent;
1facf9fc 9113+
027c5e7a 9114+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 9115+ return simple_reval_dpath(dentry, sigen);
9116+
9117+ /* slow loop, keep it simple and stupid */
9118+ /* cf: au_cpup_dirs() */
9119+ err = 0;
9120+ parent = NULL;
027c5e7a 9121+ while (au_digen_test(dentry, sigen)) {
1facf9fc 9122+ d = dentry;
9123+ while (1) {
9124+ dput(parent);
9125+ parent = dget_parent(d);
027c5e7a 9126+ if (!au_digen_test(parent, sigen))
1facf9fc 9127+ break;
9128+ d = parent;
9129+ }
9130+
1facf9fc 9131+ if (d != dentry)
027c5e7a 9132+ di_write_lock_child2(d);
1facf9fc 9133+
9134+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
9135+ if (au_digen_test(d, sigen)) {
9136+ /*
9137+ * todo: consolidate with simple_reval_dpath(),
9138+ * do_refresh() and au_reval_for_attr().
9139+ */
1facf9fc 9140+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 9141+ err = au_refresh_dentry(d, parent);
1facf9fc 9142+ di_read_unlock(parent, AuLock_IR);
9143+ }
9144+
9145+ if (d != dentry)
9146+ di_write_unlock(d);
9147+ dput(parent);
9148+ if (unlikely(err))
9149+ break;
9150+ }
9151+
9152+ return err;
9153+}
9154+
9155+/*
9156+ * if valid returns 1, otherwise 0.
9157+ */
b4510431 9158+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags)
1facf9fc 9159+{
9160+ int valid, err;
9161+ unsigned int sigen;
8b6a4947 9162+ unsigned char do_udba, dirren;
1facf9fc 9163+ struct super_block *sb;
9164+ struct inode *inode;
9165+
027c5e7a 9166+ /* todo: support rcu-walk? */
b4510431 9167+ if (flags & LOOKUP_RCU)
027c5e7a
AM
9168+ return -ECHILD;
9169+
9170+ valid = 0;
9171+ if (unlikely(!au_di(dentry)))
9172+ goto out;
9173+
e49829fe 9174+ valid = 1;
1facf9fc 9175+ sb = dentry->d_sb;
e49829fe
JR
9176+ /*
9177+ * todo: very ugly
9178+ * i_mutex of parent dir may be held,
9179+ * but we should not return 'invalid' due to busy.
9180+ */
9181+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
9182+ if (unlikely(err)) {
9183+ valid = err;
027c5e7a 9184+ AuTraceErr(err);
e49829fe
JR
9185+ goto out;
9186+ }
5527c038
JR
9187+ inode = NULL;
9188+ if (d_really_is_positive(dentry))
9189+ inode = d_inode(dentry);
5afbbe0d 9190+ if (unlikely(inode && au_is_bad_inode(inode))) {
c1595e42
JR
9191+ err = -EINVAL;
9192+ AuTraceErr(err);
9193+ goto out_dgrade;
9194+ }
027c5e7a
AM
9195+ if (unlikely(au_dbrange_test(dentry))) {
9196+ err = -EINVAL;
9197+ AuTraceErr(err);
9198+ goto out_dgrade;
1facf9fc 9199+ }
027c5e7a
AM
9200+
9201+ sigen = au_sigen(sb);
9202+ if (au_digen_test(dentry, sigen)) {
1facf9fc 9203+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
9204+ err = au_reval_dpath(dentry, sigen);
9205+ if (unlikely(err)) {
9206+ AuTraceErr(err);
1facf9fc 9207+ goto out_dgrade;
027c5e7a 9208+ }
1facf9fc 9209+ }
9210+ di_downgrade_lock(dentry, AuLock_IR);
9211+
1facf9fc 9212+ err = -EINVAL;
c1595e42 9213+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY))
523b37e3 9214+ && inode
38d290e6 9215+ && !(inode->i_state && I_LINKABLE)
79b8bda9
AM
9216+ && (IS_DEADDIR(inode) || !inode->i_nlink)) {
9217+ AuTraceErr(err);
027c5e7a 9218+ goto out_inval;
79b8bda9 9219+ }
027c5e7a 9220+
1facf9fc 9221+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
9222+ if (do_udba && inode) {
5afbbe0d 9223+ aufs_bindex_t btop = au_ibtop(inode);
027c5e7a 9224+ struct inode *h_inode;
1facf9fc 9225+
5afbbe0d
AM
9226+ if (btop >= 0) {
9227+ h_inode = au_h_iptr(inode, btop);
79b8bda9
AM
9228+ if (h_inode && au_test_higen(inode, h_inode)) {
9229+ AuTraceErr(err);
027c5e7a 9230+ goto out_inval;
79b8bda9 9231+ }
027c5e7a 9232+ }
1facf9fc 9233+ }
9234+
8b6a4947
AM
9235+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
9236+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren);
5afbbe0d 9237+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) {
1facf9fc 9238+ err = -EIO;
523b37e3
AM
9239+ AuDbg("both of real entry and whiteout found, %p, err %d\n",
9240+ dentry, err);
027c5e7a 9241+ }
e49829fe 9242+ goto out_inval;
1facf9fc 9243+
4f0767ce 9244+out_dgrade:
1facf9fc 9245+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 9246+out_inval:
1facf9fc 9247+ aufs_read_unlock(dentry, AuLock_IR);
9248+ AuTraceErr(err);
9249+ valid = !err;
e49829fe 9250+out:
027c5e7a 9251+ if (!valid) {
523b37e3 9252+ AuDbg("%pd invalid, %d\n", dentry, valid);
027c5e7a
AM
9253+ d_drop(dentry);
9254+ }
1facf9fc 9255+ return valid;
9256+}
9257+
9258+static void aufs_d_release(struct dentry *dentry)
9259+{
027c5e7a 9260+ if (au_di(dentry)) {
4a4d8108
AM
9261+ au_di_fin(dentry);
9262+ au_hn_di_reinit(dentry);
1facf9fc 9263+ }
1facf9fc 9264+}
9265+
4a4d8108 9266+const struct dentry_operations aufs_dop = {
c06a8ce3
AM
9267+ .d_revalidate = aufs_d_revalidate,
9268+ .d_weak_revalidate = aufs_d_revalidate,
9269+ .d_release = aufs_d_release
1facf9fc 9270+};
79b8bda9
AM
9271+
9272+/* aufs_dop without d_revalidate */
9273+const struct dentry_operations aufs_dop_noreval = {
9274+ .d_release = aufs_d_release
9275+};
7f207e10 9276diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
eca34b5c
AM
9277--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
9278+++ linux/fs/aufs/dentry.h 2019-07-11 15:42:14.462237786 +0200
9f237c51 9279@@ -0,0 +1,268 @@
062440b3 9280+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 9281+/*
ba1aed25 9282+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 9283+ *
9284+ * This program, aufs is free software; you can redistribute it and/or modify
9285+ * it under the terms of the GNU General Public License as published by
9286+ * the Free Software Foundation; either version 2 of the License, or
9287+ * (at your option) any later version.
dece6358
AM
9288+ *
9289+ * This program is distributed in the hope that it will be useful,
9290+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9291+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9292+ * GNU General Public License for more details.
9293+ *
9294+ * You should have received a copy of the GNU General Public License
523b37e3 9295+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9296+ */
9297+
9298+/*
9299+ * lookup and dentry operations
9300+ */
9301+
9302+#ifndef __AUFS_DENTRY_H__
9303+#define __AUFS_DENTRY_H__
9304+
9305+#ifdef __KERNEL__
9306+
dece6358 9307+#include <linux/dcache.h>
8b6a4947 9308+#include "dirren.h"
1facf9fc 9309+#include "rwsem.h"
9310+
1facf9fc 9311+struct au_hdentry {
9312+ struct dentry *hd_dentry;
027c5e7a 9313+ aufs_bindex_t hd_id;
1facf9fc 9314+};
9315+
9316+struct au_dinfo {
9317+ atomic_t di_generation;
9318+
dece6358 9319+ struct au_rwsem di_rwsem;
5afbbe0d 9320+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq;
38d290e6 9321+ unsigned char di_tmpfile; /* to allow the different name */
1c60b727 9322+ struct au_hdentry *di_hdentry;
9f237c51 9323+ struct rcu_head rcu;
4a4d8108 9324+} ____cacheline_aligned_in_smp;
1facf9fc 9325+
9326+/* ---------------------------------------------------------------------- */
9327+
5afbbe0d
AM
9328+/* flags for au_lkup_dentry() */
9329+#define AuLkup_ALLOW_NEG 1
9330+#define AuLkup_IGNORE_PERM (1 << 1)
8b6a4947 9331+#define AuLkup_DIRREN (1 << 2)
5afbbe0d
AM
9332+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
9333+#define au_fset_lkup(flags, name) \
9334+ do { (flags) |= AuLkup_##name; } while (0)
9335+#define au_fclr_lkup(flags, name) \
9336+ do { (flags) &= ~AuLkup_##name; } while (0)
9337+
8b6a4947
AM
9338+#ifndef CONFIG_AUFS_DIRREN
9339+#undef AuLkup_DIRREN
9340+#define AuLkup_DIRREN 0
9341+#endif
9342+
9343+struct au_do_lookup_args {
9344+ unsigned int flags;
9345+ mode_t type;
9346+ struct qstr whname, *name;
9347+ struct au_dr_lookup dirren;
9348+};
9349+
5afbbe0d
AM
9350+/* ---------------------------------------------------------------------- */
9351+
1facf9fc 9352+/* dentry.c */
79b8bda9 9353+extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
1facf9fc 9354+struct au_branch;
076b876e 9355+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
1facf9fc 9356+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
9357+ struct dentry *h_parent, struct au_branch *br);
9358+
5afbbe0d
AM
9359+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
9360+ unsigned int flags);
86dc4139 9361+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
027c5e7a 9362+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 9363+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
79b8bda9 9364+void au_refresh_dop(struct dentry *dentry, int force_reval);
1facf9fc 9365+
9366+/* dinfo.c */
4a4d8108 9367+void au_di_init_once(void *_di);
027c5e7a
AM
9368+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
9369+void au_di_free(struct au_dinfo *dinfo);
9370+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
9371+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
9372+int au_di_init(struct dentry *dentry);
9373+void au_di_fin(struct dentry *dentry);
e2f27e51 9374+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink);
1facf9fc 9375+
9376+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
9377+void di_read_unlock(struct dentry *d, int flags);
9378+void di_downgrade_lock(struct dentry *d, int flags);
9379+void di_write_lock(struct dentry *d, unsigned int lsc);
9380+void di_write_unlock(struct dentry *d);
9381+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
9382+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
9383+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
9384+
9385+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 9386+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 9387+aufs_bindex_t au_dbtail(struct dentry *dentry);
9388+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
9389+
9390+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9391+ struct dentry *h_dentry);
027c5e7a
AM
9392+int au_digen_test(struct dentry *dentry, unsigned int sigen);
9393+int au_dbrange_test(struct dentry *dentry);
1facf9fc 9394+void au_update_digen(struct dentry *dentry);
9395+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5afbbe0d
AM
9396+void au_update_dbtop(struct dentry *dentry);
9397+void au_update_dbbot(struct dentry *dentry);
1facf9fc 9398+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
9399+
9400+/* ---------------------------------------------------------------------- */
9401+
9402+static inline struct au_dinfo *au_di(struct dentry *dentry)
9403+{
9404+ return dentry->d_fsdata;
9405+}
9406+
9407+/* ---------------------------------------------------------------------- */
9408+
9409+/* lock subclass for dinfo */
9410+enum {
9411+ AuLsc_DI_CHILD, /* child first */
4a4d8108 9412+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 9413+ AuLsc_DI_CHILD3, /* copyup dirs */
9414+ AuLsc_DI_PARENT,
9415+ AuLsc_DI_PARENT2,
027c5e7a
AM
9416+ AuLsc_DI_PARENT3,
9417+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 9418+};
9419+
9420+/*
9421+ * di_read_lock_child, di_write_lock_child,
9422+ * di_read_lock_child2, di_write_lock_child2,
9423+ * di_read_lock_child3, di_write_lock_child3,
9424+ * di_read_lock_parent, di_write_lock_parent,
9425+ * di_read_lock_parent2, di_write_lock_parent2,
9426+ * di_read_lock_parent3, di_write_lock_parent3,
9427+ */
9428+#define AuReadLockFunc(name, lsc) \
9429+static inline void di_read_lock_##name(struct dentry *d, int flags) \
9430+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
9431+
9432+#define AuWriteLockFunc(name, lsc) \
9433+static inline void di_write_lock_##name(struct dentry *d) \
9434+{ di_write_lock(d, AuLsc_DI_##lsc); }
9435+
9436+#define AuRWLockFuncs(name, lsc) \
9437+ AuReadLockFunc(name, lsc) \
9438+ AuWriteLockFunc(name, lsc)
9439+
9440+AuRWLockFuncs(child, CHILD);
9441+AuRWLockFuncs(child2, CHILD2);
9442+AuRWLockFuncs(child3, CHILD3);
9443+AuRWLockFuncs(parent, PARENT);
9444+AuRWLockFuncs(parent2, PARENT2);
9445+AuRWLockFuncs(parent3, PARENT3);
9446+
9447+#undef AuReadLockFunc
9448+#undef AuWriteLockFunc
9449+#undef AuRWLockFuncs
9450+
9451+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
9452+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
9453+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 9454+
9455+/* ---------------------------------------------------------------------- */
9456+
9457+/* todo: memory barrier? */
9458+static inline unsigned int au_digen(struct dentry *d)
9459+{
9460+ return atomic_read(&au_di(d)->di_generation);
9461+}
9462+
9463+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
9464+{
9465+ hdentry->hd_dentry = NULL;
9466+}
9467+
5afbbe0d
AM
9468+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di,
9469+ aufs_bindex_t bindex)
9470+{
9471+ return di->di_hdentry + bindex;
9472+}
9473+
1facf9fc 9474+static inline void au_hdput(struct au_hdentry *hd)
9475+{
4a4d8108
AM
9476+ if (hd)
9477+ dput(hd->hd_dentry);
1facf9fc 9478+}
9479+
5afbbe0d 9480+static inline aufs_bindex_t au_dbtop(struct dentry *dentry)
1facf9fc 9481+{
1308ab2a 9482+ DiMustAnyLock(dentry);
5afbbe0d 9483+ return au_di(dentry)->di_btop;
1facf9fc 9484+}
9485+
5afbbe0d 9486+static inline aufs_bindex_t au_dbbot(struct dentry *dentry)
1facf9fc 9487+{
1308ab2a 9488+ DiMustAnyLock(dentry);
5afbbe0d 9489+ return au_di(dentry)->di_bbot;
1facf9fc 9490+}
9491+
9492+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
9493+{
1308ab2a 9494+ DiMustAnyLock(dentry);
1facf9fc 9495+ return au_di(dentry)->di_bwh;
9496+}
9497+
9498+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
9499+{
1308ab2a 9500+ DiMustAnyLock(dentry);
1facf9fc 9501+ return au_di(dentry)->di_bdiropq;
9502+}
9503+
9504+/* todo: hard/soft set? */
5afbbe0d 9505+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9506+{
1308ab2a 9507+ DiMustWriteLock(dentry);
5afbbe0d 9508+ au_di(dentry)->di_btop = bindex;
1facf9fc 9509+}
9510+
5afbbe0d 9511+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9512+{
1308ab2a 9513+ DiMustWriteLock(dentry);
5afbbe0d 9514+ au_di(dentry)->di_bbot = bindex;
1facf9fc 9515+}
9516+
9517+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
9518+{
1308ab2a 9519+ DiMustWriteLock(dentry);
5afbbe0d 9520+ /* dbwh can be outside of btop - bbot range */
1facf9fc 9521+ au_di(dentry)->di_bwh = bindex;
9522+}
9523+
9524+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
9525+{
1308ab2a 9526+ DiMustWriteLock(dentry);
1facf9fc 9527+ au_di(dentry)->di_bdiropq = bindex;
9528+}
9529+
9530+/* ---------------------------------------------------------------------- */
9531+
4a4d8108 9532+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 9533+static inline void au_digen_dec(struct dentry *d)
9534+{
e49829fe 9535+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 9536+}
9537+
4a4d8108 9538+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 9539+{
9540+ dentry->d_fsdata = NULL;
9541+}
9542+#else
4a4d8108
AM
9543+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
9544+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 9545+
9546+#endif /* __KERNEL__ */
9547+#endif /* __AUFS_DENTRY_H__ */
7f207e10 9548diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
eca34b5c
AM
9549--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
9550+++ linux/fs/aufs/dinfo.c 2019-07-11 15:42:14.462237786 +0200
062440b3 9551@@ -0,0 +1,554 @@
cd7a4cd9 9552+// SPDX-License-Identifier: GPL-2.0
1facf9fc 9553+/*
ba1aed25 9554+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 9555+ *
9556+ * This program, aufs is free software; you can redistribute it and/or modify
9557+ * it under the terms of the GNU General Public License as published by
9558+ * the Free Software Foundation; either version 2 of the License, or
9559+ * (at your option) any later version.
dece6358
AM
9560+ *
9561+ * This program is distributed in the hope that it will be useful,
9562+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9563+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9564+ * GNU General Public License for more details.
9565+ *
9566+ * You should have received a copy of the GNU General Public License
523b37e3 9567+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9568+ */
9569+
9570+/*
9571+ * dentry private data
9572+ */
9573+
9574+#include "aufs.h"
9575+
e49829fe 9576+void au_di_init_once(void *_dinfo)
4a4d8108 9577+{
e49829fe 9578+ struct au_dinfo *dinfo = _dinfo;
4a4d8108 9579+
e49829fe 9580+ au_rw_init(&dinfo->di_rwsem);
4a4d8108
AM
9581+}
9582+
027c5e7a 9583+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 9584+{
9585+ struct au_dinfo *dinfo;
027c5e7a 9586+ int nbr, i;
1facf9fc 9587+
9588+ dinfo = au_cache_alloc_dinfo();
9589+ if (unlikely(!dinfo))
9590+ goto out;
9591+
5afbbe0d 9592+ nbr = au_sbbot(sb) + 1;
1facf9fc 9593+ if (nbr <= 0)
9594+ nbr = 1;
9595+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
9596+ if (dinfo->di_hdentry) {
9597+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
5afbbe0d
AM
9598+ dinfo->di_btop = -1;
9599+ dinfo->di_bbot = -1;
027c5e7a
AM
9600+ dinfo->di_bwh = -1;
9601+ dinfo->di_bdiropq = -1;
38d290e6 9602+ dinfo->di_tmpfile = 0;
027c5e7a
AM
9603+ for (i = 0; i < nbr; i++)
9604+ dinfo->di_hdentry[i].hd_id = -1;
9605+ goto out;
9606+ }
1facf9fc 9607+
1c60b727 9608+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9609+ dinfo = NULL;
9610+
4f0767ce 9611+out:
027c5e7a 9612+ return dinfo;
1facf9fc 9613+}
9614+
027c5e7a 9615+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 9616+{
4a4d8108 9617+ struct au_hdentry *p;
5afbbe0d 9618+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
9619+
9620+ /* dentry may not be revalidated */
5afbbe0d 9621+ bindex = dinfo->di_btop;
4a4d8108 9622+ if (bindex >= 0) {
5afbbe0d
AM
9623+ bbot = dinfo->di_bbot;
9624+ p = au_hdentry(dinfo, bindex);
9625+ while (bindex++ <= bbot)
4a4d8108
AM
9626+ au_hdput(p++);
9627+ }
9f237c51 9628+ au_kfree_try_rcu(dinfo->di_hdentry);
1c60b727 9629+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9630+}
9631+
9632+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
9633+{
9634+ struct au_hdentry *p;
9635+ aufs_bindex_t bi;
9636+
9637+ AuRwMustWriteLock(&a->di_rwsem);
9638+ AuRwMustWriteLock(&b->di_rwsem);
9639+
9640+#define DiSwap(v, name) \
9641+ do { \
9642+ v = a->di_##name; \
9643+ a->di_##name = b->di_##name; \
9644+ b->di_##name = v; \
9645+ } while (0)
9646+
9647+ DiSwap(p, hdentry);
5afbbe0d
AM
9648+ DiSwap(bi, btop);
9649+ DiSwap(bi, bbot);
027c5e7a
AM
9650+ DiSwap(bi, bwh);
9651+ DiSwap(bi, bdiropq);
9652+ /* smp_mb(); */
9653+
9654+#undef DiSwap
9655+}
9656+
9657+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
9658+{
9659+ AuRwMustWriteLock(&dst->di_rwsem);
9660+ AuRwMustWriteLock(&src->di_rwsem);
9661+
5afbbe0d
AM
9662+ dst->di_btop = src->di_btop;
9663+ dst->di_bbot = src->di_bbot;
027c5e7a
AM
9664+ dst->di_bwh = src->di_bwh;
9665+ dst->di_bdiropq = src->di_bdiropq;
9666+ /* smp_mb(); */
9667+}
9668+
9669+int au_di_init(struct dentry *dentry)
9670+{
9671+ int err;
9672+ struct super_block *sb;
9673+ struct au_dinfo *dinfo;
9674+
9675+ err = 0;
9676+ sb = dentry->d_sb;
9677+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
9678+ if (dinfo) {
9679+ atomic_set(&dinfo->di_generation, au_sigen(sb));
9680+ /* smp_mb(); */ /* atomic_set */
9681+ dentry->d_fsdata = dinfo;
9682+ } else
9683+ err = -ENOMEM;
9684+
9685+ return err;
9686+}
9687+
9688+void au_di_fin(struct dentry *dentry)
9689+{
9690+ struct au_dinfo *dinfo;
9691+
9692+ dinfo = au_di(dentry);
9693+ AuRwDestroy(&dinfo->di_rwsem);
9694+ au_di_free(dinfo);
4a4d8108
AM
9695+}
9696+
e2f27e51 9697+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink)
1facf9fc 9698+{
9699+ int err, sz;
9700+ struct au_hdentry *hdp;
9701+
1308ab2a 9702+ AuRwMustWriteLock(&dinfo->di_rwsem);
9703+
1facf9fc 9704+ err = -ENOMEM;
5afbbe0d 9705+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1);
1facf9fc 9706+ if (!sz)
9707+ sz = sizeof(*hdp);
e2f27e51
AM
9708+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS,
9709+ may_shrink);
1facf9fc 9710+ if (hdp) {
9711+ dinfo->di_hdentry = hdp;
9712+ err = 0;
9713+ }
9714+
9715+ return err;
9716+}
9717+
9718+/* ---------------------------------------------------------------------- */
9719+
9720+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
9721+{
9722+ switch (lsc) {
9723+ case AuLsc_DI_CHILD:
9724+ ii_write_lock_child(inode);
9725+ break;
9726+ case AuLsc_DI_CHILD2:
9727+ ii_write_lock_child2(inode);
9728+ break;
9729+ case AuLsc_DI_CHILD3:
9730+ ii_write_lock_child3(inode);
9731+ break;
9732+ case AuLsc_DI_PARENT:
9733+ ii_write_lock_parent(inode);
9734+ break;
9735+ case AuLsc_DI_PARENT2:
9736+ ii_write_lock_parent2(inode);
9737+ break;
9738+ case AuLsc_DI_PARENT3:
9739+ ii_write_lock_parent3(inode);
9740+ break;
9741+ default:
9742+ BUG();
9743+ }
9744+}
9745+
9746+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
9747+{
9748+ switch (lsc) {
9749+ case AuLsc_DI_CHILD:
9750+ ii_read_lock_child(inode);
9751+ break;
9752+ case AuLsc_DI_CHILD2:
9753+ ii_read_lock_child2(inode);
9754+ break;
9755+ case AuLsc_DI_CHILD3:
9756+ ii_read_lock_child3(inode);
9757+ break;
9758+ case AuLsc_DI_PARENT:
9759+ ii_read_lock_parent(inode);
9760+ break;
9761+ case AuLsc_DI_PARENT2:
9762+ ii_read_lock_parent2(inode);
9763+ break;
9764+ case AuLsc_DI_PARENT3:
9765+ ii_read_lock_parent3(inode);
9766+ break;
9767+ default:
9768+ BUG();
9769+ }
9770+}
9771+
9772+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
9773+{
5527c038
JR
9774+ struct inode *inode;
9775+
dece6358 9776+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9777+ if (d_really_is_positive(d)) {
9778+ inode = d_inode(d);
1facf9fc 9779+ if (au_ftest_lock(flags, IW))
5527c038 9780+ do_ii_write_lock(inode, lsc);
1facf9fc 9781+ else if (au_ftest_lock(flags, IR))
5527c038 9782+ do_ii_read_lock(inode, lsc);
1facf9fc 9783+ }
9784+}
9785+
9786+void di_read_unlock(struct dentry *d, int flags)
9787+{
5527c038
JR
9788+ struct inode *inode;
9789+
9790+ if (d_really_is_positive(d)) {
9791+ inode = d_inode(d);
027c5e7a
AM
9792+ if (au_ftest_lock(flags, IW)) {
9793+ au_dbg_verify_dinode(d);
5527c038 9794+ ii_write_unlock(inode);
027c5e7a
AM
9795+ } else if (au_ftest_lock(flags, IR)) {
9796+ au_dbg_verify_dinode(d);
5527c038 9797+ ii_read_unlock(inode);
027c5e7a 9798+ }
1facf9fc 9799+ }
dece6358 9800+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 9801+}
9802+
9803+void di_downgrade_lock(struct dentry *d, int flags)
9804+{
5527c038
JR
9805+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR))
9806+ ii_downgrade_lock(d_inode(d));
dece6358 9807+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 9808+}
9809+
9810+void di_write_lock(struct dentry *d, unsigned int lsc)
9811+{
dece6358 9812+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9813+ if (d_really_is_positive(d))
9814+ do_ii_write_lock(d_inode(d), lsc);
1facf9fc 9815+}
9816+
9817+void di_write_unlock(struct dentry *d)
9818+{
027c5e7a 9819+ au_dbg_verify_dinode(d);
5527c038
JR
9820+ if (d_really_is_positive(d))
9821+ ii_write_unlock(d_inode(d));
dece6358 9822+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 9823+}
9824+
9825+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
9826+{
9827+ AuDebugOn(d1 == d2
5527c038 9828+ || d_inode(d1) == d_inode(d2)
1facf9fc 9829+ || d1->d_sb != d2->d_sb);
9830+
521ced18
JR
9831+ if ((isdir && au_test_subdir(d1, d2))
9832+ || d1 < d2) {
1facf9fc 9833+ di_write_lock_child(d1);
9834+ di_write_lock_child2(d2);
9835+ } else {
1facf9fc 9836+ di_write_lock_child(d2);
9837+ di_write_lock_child2(d1);
9838+ }
9839+}
9840+
9841+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
9842+{
9843+ AuDebugOn(d1 == d2
5527c038 9844+ || d_inode(d1) == d_inode(d2)
1facf9fc 9845+ || d1->d_sb != d2->d_sb);
9846+
521ced18
JR
9847+ if ((isdir && au_test_subdir(d1, d2))
9848+ || d1 < d2) {
1facf9fc 9849+ di_write_lock_parent(d1);
9850+ di_write_lock_parent2(d2);
9851+ } else {
1facf9fc 9852+ di_write_lock_parent(d2);
9853+ di_write_lock_parent2(d1);
9854+ }
9855+}
9856+
9857+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
9858+{
9859+ di_write_unlock(d1);
5527c038 9860+ if (d_inode(d1) == d_inode(d2))
dece6358 9861+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 9862+ else
9863+ di_write_unlock(d2);
9864+}
9865+
9866+/* ---------------------------------------------------------------------- */
9867+
9868+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
9869+{
9870+ struct dentry *d;
9871+
1308ab2a 9872+ DiMustAnyLock(dentry);
9873+
5afbbe0d 9874+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
1facf9fc 9875+ return NULL;
9876+ AuDebugOn(bindex < 0);
5afbbe0d 9877+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry;
c1595e42 9878+ AuDebugOn(d && au_dcount(d) <= 0);
1facf9fc 9879+ return d;
9880+}
9881+
2cbb1c4b
JR
9882+/*
9883+ * extended version of au_h_dptr().
38d290e6
JR
9884+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or
9885+ * error.
2cbb1c4b
JR
9886+ */
9887+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
9888+{
9889+ struct dentry *h_dentry;
9890+ struct inode *inode, *h_inode;
9891+
5527c038 9892+ AuDebugOn(d_really_is_negative(dentry));
2cbb1c4b
JR
9893+
9894+ h_dentry = NULL;
5afbbe0d
AM
9895+ if (au_dbtop(dentry) <= bindex
9896+ && bindex <= au_dbbot(dentry))
2cbb1c4b 9897+ h_dentry = au_h_dptr(dentry, bindex);
38d290e6 9898+ if (h_dentry && !au_d_linkable(h_dentry)) {
2cbb1c4b
JR
9899+ dget(h_dentry);
9900+ goto out; /* success */
9901+ }
9902+
5527c038 9903+ inode = d_inode(dentry);
5afbbe0d
AM
9904+ AuDebugOn(bindex < au_ibtop(inode));
9905+ AuDebugOn(au_ibbot(inode) < bindex);
2cbb1c4b
JR
9906+ h_inode = au_h_iptr(inode, bindex);
9907+ h_dentry = d_find_alias(h_inode);
9908+ if (h_dentry) {
9909+ if (!IS_ERR(h_dentry)) {
38d290e6 9910+ if (!au_d_linkable(h_dentry))
2cbb1c4b
JR
9911+ goto out; /* success */
9912+ dput(h_dentry);
9913+ } else
9914+ goto out;
9915+ }
9916+
9917+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
9918+ h_dentry = au_plink_lkup(inode, bindex);
9919+ AuDebugOn(!h_dentry);
9920+ if (!IS_ERR(h_dentry)) {
9921+ if (!au_d_hashed_positive(h_dentry))
9922+ goto out; /* success */
9923+ dput(h_dentry);
9924+ h_dentry = NULL;
9925+ }
9926+ }
9927+
9928+out:
9929+ AuDbgDentry(h_dentry);
9930+ return h_dentry;
9931+}
9932+
1facf9fc 9933+aufs_bindex_t au_dbtail(struct dentry *dentry)
9934+{
5afbbe0d 9935+ aufs_bindex_t bbot, bwh;
1facf9fc 9936+
5afbbe0d
AM
9937+ bbot = au_dbbot(dentry);
9938+ if (0 <= bbot) {
1facf9fc 9939+ bwh = au_dbwh(dentry);
9940+ if (!bwh)
9941+ return bwh;
5afbbe0d 9942+ if (0 < bwh && bwh < bbot)
1facf9fc 9943+ return bwh - 1;
9944+ }
5afbbe0d 9945+ return bbot;
1facf9fc 9946+}
9947+
9948+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
9949+{
5afbbe0d 9950+ aufs_bindex_t bbot, bopq;
1facf9fc 9951+
5afbbe0d
AM
9952+ bbot = au_dbtail(dentry);
9953+ if (0 <= bbot) {
1facf9fc 9954+ bopq = au_dbdiropq(dentry);
5afbbe0d
AM
9955+ if (0 <= bopq && bopq < bbot)
9956+ bbot = bopq;
1facf9fc 9957+ }
5afbbe0d 9958+ return bbot;
1facf9fc 9959+}
9960+
9961+/* ---------------------------------------------------------------------- */
9962+
9963+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9964+ struct dentry *h_dentry)
9965+{
5afbbe0d
AM
9966+ struct au_dinfo *dinfo;
9967+ struct au_hdentry *hd;
027c5e7a 9968+ struct au_branch *br;
1facf9fc 9969+
1308ab2a 9970+ DiMustWriteLock(dentry);
9971+
5afbbe0d
AM
9972+ dinfo = au_di(dentry);
9973+ hd = au_hdentry(dinfo, bindex);
4a4d8108 9974+ au_hdput(hd);
1facf9fc 9975+ hd->hd_dentry = h_dentry;
027c5e7a
AM
9976+ if (h_dentry) {
9977+ br = au_sbr(dentry->d_sb, bindex);
9978+ hd->hd_id = br->br_id;
9979+ }
9980+}
9981+
9982+int au_dbrange_test(struct dentry *dentry)
9983+{
9984+ int err;
5afbbe0d 9985+ aufs_bindex_t btop, bbot;
027c5e7a
AM
9986+
9987+ err = 0;
5afbbe0d
AM
9988+ btop = au_dbtop(dentry);
9989+ bbot = au_dbbot(dentry);
9990+ if (btop >= 0)
9991+ AuDebugOn(bbot < 0 && btop > bbot);
027c5e7a
AM
9992+ else {
9993+ err = -EIO;
5afbbe0d 9994+ AuDebugOn(bbot >= 0);
027c5e7a
AM
9995+ }
9996+
9997+ return err;
9998+}
9999+
10000+int au_digen_test(struct dentry *dentry, unsigned int sigen)
10001+{
10002+ int err;
10003+
10004+ err = 0;
10005+ if (unlikely(au_digen(dentry) != sigen
5527c038 10006+ || au_iigen_test(d_inode(dentry), sigen)))
027c5e7a
AM
10007+ err = -EIO;
10008+
10009+ return err;
1facf9fc 10010+}
10011+
10012+void au_update_digen(struct dentry *dentry)
10013+{
10014+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
10015+ /* smp_mb(); */ /* atomic_set */
10016+}
10017+
10018+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
10019+{
10020+ struct au_dinfo *dinfo;
10021+ struct dentry *h_d;
4a4d8108 10022+ struct au_hdentry *hdp;
5afbbe0d 10023+ aufs_bindex_t bindex, bbot;
1facf9fc 10024+
1308ab2a 10025+ DiMustWriteLock(dentry);
10026+
1facf9fc 10027+ dinfo = au_di(dentry);
5afbbe0d 10028+ if (!dinfo || dinfo->di_btop < 0)
1facf9fc 10029+ return;
10030+
10031+ if (do_put_zero) {
5afbbe0d
AM
10032+ bbot = dinfo->di_bbot;
10033+ bindex = dinfo->di_btop;
10034+ hdp = au_hdentry(dinfo, bindex);
10035+ for (; bindex <= bbot; bindex++, hdp++) {
10036+ h_d = hdp->hd_dentry;
5527c038 10037+ if (h_d && d_is_negative(h_d))
1facf9fc 10038+ au_set_h_dptr(dentry, bindex, NULL);
10039+ }
10040+ }
10041+
5afbbe0d
AM
10042+ dinfo->di_btop = 0;
10043+ hdp = au_hdentry(dinfo, dinfo->di_btop);
10044+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++)
10045+ if (hdp->hd_dentry)
1facf9fc 10046+ break;
5afbbe0d
AM
10047+ if (dinfo->di_btop > dinfo->di_bbot) {
10048+ dinfo->di_btop = -1;
10049+ dinfo->di_bbot = -1;
1facf9fc 10050+ return;
10051+ }
10052+
5afbbe0d
AM
10053+ hdp = au_hdentry(dinfo, dinfo->di_bbot);
10054+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--)
10055+ if (hdp->hd_dentry)
1facf9fc 10056+ break;
5afbbe0d 10057+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0);
1facf9fc 10058+}
10059+
5afbbe0d 10060+void au_update_dbtop(struct dentry *dentry)
1facf9fc 10061+{
5afbbe0d 10062+ aufs_bindex_t bindex, bbot;
1facf9fc 10063+ struct dentry *h_dentry;
10064+
5afbbe0d
AM
10065+ bbot = au_dbbot(dentry);
10066+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
1facf9fc 10067+ h_dentry = au_h_dptr(dentry, bindex);
10068+ if (!h_dentry)
10069+ continue;
5527c038 10070+ if (d_is_positive(h_dentry)) {
5afbbe0d 10071+ au_set_dbtop(dentry, bindex);
1facf9fc 10072+ return;
10073+ }
10074+ au_set_h_dptr(dentry, bindex, NULL);
10075+ }
10076+}
10077+
5afbbe0d 10078+void au_update_dbbot(struct dentry *dentry)
1facf9fc 10079+{
5afbbe0d 10080+ aufs_bindex_t bindex, btop;
1facf9fc 10081+ struct dentry *h_dentry;
10082+
5afbbe0d
AM
10083+ btop = au_dbtop(dentry);
10084+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) {
1facf9fc 10085+ h_dentry = au_h_dptr(dentry, bindex);
10086+ if (!h_dentry)
10087+ continue;
5527c038 10088+ if (d_is_positive(h_dentry)) {
5afbbe0d 10089+ au_set_dbbot(dentry, bindex);
1facf9fc 10090+ return;
10091+ }
10092+ au_set_h_dptr(dentry, bindex, NULL);
10093+ }
10094+}
10095+
10096+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
10097+{
5afbbe0d 10098+ aufs_bindex_t bindex, bbot;
1facf9fc 10099+
5afbbe0d
AM
10100+ bbot = au_dbbot(dentry);
10101+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++)
1facf9fc 10102+ if (au_h_dptr(dentry, bindex) == h_dentry)
10103+ return bindex;
10104+ return -1;
10105+}
7f207e10 10106diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
eca34b5c
AM
10107--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
10108+++ linux/fs/aufs/dir.c 2019-07-11 15:42:14.462237786 +0200
eca801bf 10109@@ -0,0 +1,763 @@
cd7a4cd9 10110+// SPDX-License-Identifier: GPL-2.0
1facf9fc 10111+/*
ba1aed25 10112+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 10113+ *
10114+ * This program, aufs is free software; you can redistribute it and/or modify
10115+ * it under the terms of the GNU General Public License as published by
10116+ * the Free Software Foundation; either version 2 of the License, or
10117+ * (at your option) any later version.
dece6358
AM
10118+ *
10119+ * This program is distributed in the hope that it will be useful,
10120+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10121+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10122+ * GNU General Public License for more details.
10123+ *
10124+ * You should have received a copy of the GNU General Public License
523b37e3 10125+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10126+ */
10127+
10128+/*
10129+ * directory operations
10130+ */
10131+
10132+#include <linux/fs_stack.h>
eca801bf 10133+#include <linux/iversion.h>
1facf9fc 10134+#include "aufs.h"
10135+
10136+void au_add_nlink(struct inode *dir, struct inode *h_dir)
10137+{
9dbd164d
AM
10138+ unsigned int nlink;
10139+
1facf9fc 10140+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
10141+
9dbd164d
AM
10142+ nlink = dir->i_nlink;
10143+ nlink += h_dir->i_nlink - 2;
1facf9fc 10144+ if (h_dir->i_nlink < 2)
9dbd164d 10145+ nlink += 2;
f6b6e03d 10146+ smp_mb(); /* for i_nlink */
7eafdf33 10147+ /* 0 can happen in revaliding */
92d182d2 10148+ set_nlink(dir, nlink);
1facf9fc 10149+}
10150+
10151+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
10152+{
9dbd164d
AM
10153+ unsigned int nlink;
10154+
1facf9fc 10155+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
10156+
9dbd164d
AM
10157+ nlink = dir->i_nlink;
10158+ nlink -= h_dir->i_nlink - 2;
1facf9fc 10159+ if (h_dir->i_nlink < 2)
9dbd164d 10160+ nlink -= 2;
f6b6e03d 10161+ smp_mb(); /* for i_nlink */
92d182d2 10162+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 10163+ set_nlink(dir, nlink);
1facf9fc 10164+}
10165+
1308ab2a 10166+loff_t au_dir_size(struct file *file, struct dentry *dentry)
10167+{
10168+ loff_t sz;
5afbbe0d 10169+ aufs_bindex_t bindex, bbot;
1308ab2a 10170+ struct file *h_file;
10171+ struct dentry *h_dentry;
10172+
10173+ sz = 0;
10174+ if (file) {
2000de60 10175+ AuDebugOn(!d_is_dir(file->f_path.dentry));
1308ab2a 10176+
5afbbe0d
AM
10177+ bbot = au_fbbot_dir(file);
10178+ for (bindex = au_fbtop(file);
10179+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10180+ bindex++) {
4a4d8108 10181+ h_file = au_hf_dir(file, bindex);
c06a8ce3
AM
10182+ if (h_file && file_inode(h_file))
10183+ sz += vfsub_f_size_read(h_file);
1308ab2a 10184+ }
10185+ } else {
10186+ AuDebugOn(!dentry);
2000de60 10187+ AuDebugOn(!d_is_dir(dentry));
1308ab2a 10188+
5afbbe0d
AM
10189+ bbot = au_dbtaildir(dentry);
10190+ for (bindex = au_dbtop(dentry);
10191+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10192+ bindex++) {
10193+ h_dentry = au_h_dptr(dentry, bindex);
5527c038
JR
10194+ if (h_dentry && d_is_positive(h_dentry))
10195+ sz += i_size_read(d_inode(h_dentry));
1308ab2a 10196+ }
10197+ }
10198+ if (sz < KMALLOC_MAX_SIZE)
10199+ sz = roundup_pow_of_two(sz);
10200+ if (sz > KMALLOC_MAX_SIZE)
10201+ sz = KMALLOC_MAX_SIZE;
10202+ else if (sz < NAME_MAX) {
10203+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
10204+ sz = AUFS_RDBLK_DEF;
10205+ }
10206+ return sz;
10207+}
10208+
b912730e
AM
10209+struct au_dir_ts_arg {
10210+ struct dentry *dentry;
10211+ aufs_bindex_t brid;
10212+};
10213+
10214+static void au_do_dir_ts(void *arg)
10215+{
10216+ struct au_dir_ts_arg *a = arg;
10217+ struct au_dtime dt;
10218+ struct path h_path;
10219+ struct inode *dir, *h_dir;
10220+ struct super_block *sb;
10221+ struct au_branch *br;
10222+ struct au_hinode *hdir;
10223+ int err;
5afbbe0d 10224+ aufs_bindex_t btop, bindex;
b912730e
AM
10225+
10226+ sb = a->dentry->d_sb;
5527c038 10227+ if (d_really_is_negative(a->dentry))
b912730e 10228+ goto out;
5527c038 10229+ /* no dir->i_mutex lock */
b95c5147
AM
10230+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */
10231+
5527c038 10232+ dir = d_inode(a->dentry);
5afbbe0d 10233+ btop = au_ibtop(dir);
b912730e 10234+ bindex = au_br_index(sb, a->brid);
5afbbe0d 10235+ if (bindex < btop)
b912730e
AM
10236+ goto out_unlock;
10237+
10238+ br = au_sbr(sb, bindex);
10239+ h_path.dentry = au_h_dptr(a->dentry, bindex);
10240+ if (!h_path.dentry)
10241+ goto out_unlock;
10242+ h_path.mnt = au_br_mnt(br);
10243+ au_dtime_store(&dt, a->dentry, &h_path);
10244+
5afbbe0d 10245+ br = au_sbr(sb, btop);
b912730e
AM
10246+ if (!au_br_writable(br->br_perm))
10247+ goto out_unlock;
5afbbe0d 10248+ h_path.dentry = au_h_dptr(a->dentry, btop);
b912730e
AM
10249+ h_path.mnt = au_br_mnt(br);
10250+ err = vfsub_mnt_want_write(h_path.mnt);
10251+ if (err)
10252+ goto out_unlock;
5afbbe0d
AM
10253+ hdir = au_hi(dir, btop);
10254+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
10255+ h_dir = au_h_iptr(dir, btop);
b912730e 10256+ if (h_dir->i_nlink
cd7a4cd9 10257+ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) {
b912730e
AM
10258+ dt.dt_h_path = h_path;
10259+ au_dtime_revert(&dt);
10260+ }
5afbbe0d 10261+ au_hn_inode_unlock(hdir);
b912730e
AM
10262+ vfsub_mnt_drop_write(h_path.mnt);
10263+ au_cpup_attr_timesizes(dir);
10264+
10265+out_unlock:
10266+ aufs_read_unlock(a->dentry, AuLock_DW);
10267+out:
10268+ dput(a->dentry);
10269+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 10270+ au_kfree_try_rcu(arg);
b912730e
AM
10271+}
10272+
10273+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
10274+{
10275+ int perm, wkq_err;
5afbbe0d 10276+ aufs_bindex_t btop;
b912730e
AM
10277+ struct au_dir_ts_arg *arg;
10278+ struct dentry *dentry;
10279+ struct super_block *sb;
10280+
10281+ IMustLock(dir);
10282+
10283+ dentry = d_find_any_alias(dir);
10284+ AuDebugOn(!dentry);
10285+ sb = dentry->d_sb;
5afbbe0d
AM
10286+ btop = au_ibtop(dir);
10287+ if (btop == bindex) {
b912730e
AM
10288+ au_cpup_attr_timesizes(dir);
10289+ goto out;
10290+ }
10291+
5afbbe0d 10292+ perm = au_sbr_perm(sb, btop);
b912730e
AM
10293+ if (!au_br_writable(perm))
10294+ goto out;
10295+
10296+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
10297+ if (!arg)
10298+ goto out;
10299+
10300+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */
10301+ arg->brid = au_sbr_id(sb, bindex);
10302+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0);
10303+ if (unlikely(wkq_err)) {
10304+ pr_err("wkq %d\n", wkq_err);
10305+ dput(dentry);
9f237c51 10306+ au_kfree_try_rcu(arg);
b912730e
AM
10307+ }
10308+
10309+out:
10310+ dput(dentry);
10311+}
10312+
1facf9fc 10313+/* ---------------------------------------------------------------------- */
10314+
10315+static int reopen_dir(struct file *file)
10316+{
10317+ int err;
10318+ unsigned int flags;
5afbbe0d 10319+ aufs_bindex_t bindex, btail, btop;
1facf9fc 10320+ struct dentry *dentry, *h_dentry;
10321+ struct file *h_file;
10322+
10323+ /* open all lower dirs */
2000de60 10324+ dentry = file->f_path.dentry;
5afbbe0d
AM
10325+ btop = au_dbtop(dentry);
10326+ for (bindex = au_fbtop(file); bindex < btop; bindex++)
1facf9fc 10327+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10328+ au_set_fbtop(file, btop);
1facf9fc 10329+
10330+ btail = au_dbtaildir(dentry);
5afbbe0d 10331+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--)
1facf9fc 10332+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10333+ au_set_fbbot_dir(file, btail);
1facf9fc 10334+
4a4d8108 10335+ flags = vfsub_file_flags(file);
5afbbe0d 10336+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 10337+ h_dentry = au_h_dptr(dentry, bindex);
10338+ if (!h_dentry)
10339+ continue;
4a4d8108 10340+ h_file = au_hf_dir(file, bindex);
1facf9fc 10341+ if (h_file)
10342+ continue;
10343+
392086de 10344+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10345+ err = PTR_ERR(h_file);
10346+ if (IS_ERR(h_file))
10347+ goto out; /* close all? */
10348+ au_set_h_fptr(file, bindex, h_file);
10349+ }
10350+ au_update_figen(file);
10351+ /* todo: necessary? */
10352+ /* file->f_ra = h_file->f_ra; */
10353+ err = 0;
10354+
4f0767ce 10355+out:
1facf9fc 10356+ return err;
10357+}
10358+
b912730e 10359+static int do_open_dir(struct file *file, int flags, struct file *h_file)
1facf9fc 10360+{
10361+ int err;
10362+ aufs_bindex_t bindex, btail;
10363+ struct dentry *dentry, *h_dentry;
8cdd5066 10364+ struct vfsmount *mnt;
1facf9fc 10365+
1308ab2a 10366+ FiMustWriteLock(file);
b912730e 10367+ AuDebugOn(h_file);
1308ab2a 10368+
523b37e3 10369+ err = 0;
8cdd5066 10370+ mnt = file->f_path.mnt;
2000de60 10371+ dentry = file->f_path.dentry;
be118d29 10372+ file->f_version = inode_query_iversion(d_inode(dentry));
5afbbe0d
AM
10373+ bindex = au_dbtop(dentry);
10374+ au_set_fbtop(file, bindex);
1facf9fc 10375+ btail = au_dbtaildir(dentry);
5afbbe0d 10376+ au_set_fbbot_dir(file, btail);
1facf9fc 10377+ for (; !err && bindex <= btail; bindex++) {
10378+ h_dentry = au_h_dptr(dentry, bindex);
10379+ if (!h_dentry)
10380+ continue;
10381+
8cdd5066
JR
10382+ err = vfsub_test_mntns(mnt, h_dentry->d_sb);
10383+ if (unlikely(err))
10384+ break;
392086de 10385+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10386+ if (IS_ERR(h_file)) {
10387+ err = PTR_ERR(h_file);
10388+ break;
10389+ }
10390+ au_set_h_fptr(file, bindex, h_file);
10391+ }
10392+ au_update_figen(file);
10393+ /* todo: necessary? */
10394+ /* file->f_ra = h_file->f_ra; */
10395+ if (!err)
10396+ return 0; /* success */
10397+
10398+ /* close all */
5afbbe0d 10399+ for (bindex = au_fbtop(file); bindex <= btail; bindex++)
1facf9fc 10400+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d
AM
10401+ au_set_fbtop(file, -1);
10402+ au_set_fbbot_dir(file, -1);
4a4d8108 10403+
1facf9fc 10404+ return err;
10405+}
10406+
10407+static int aufs_open_dir(struct inode *inode __maybe_unused,
10408+ struct file *file)
10409+{
4a4d8108
AM
10410+ int err;
10411+ struct super_block *sb;
10412+ struct au_fidir *fidir;
10413+
10414+ err = -ENOMEM;
2000de60 10415+ sb = file->f_path.dentry->d_sb;
4a4d8108 10416+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 10417+ fidir = au_fidir_alloc(sb);
4a4d8108 10418+ if (fidir) {
b912730e
AM
10419+ struct au_do_open_args args = {
10420+ .open = do_open_dir,
10421+ .fidir = fidir
10422+ };
10423+ err = au_do_open(file, &args);
4a4d8108 10424+ if (unlikely(err))
9f237c51 10425+ au_kfree_rcu(fidir);
4a4d8108
AM
10426+ }
10427+ si_read_unlock(sb);
10428+ return err;
1facf9fc 10429+}
10430+
10431+static int aufs_release_dir(struct inode *inode __maybe_unused,
10432+ struct file *file)
10433+{
10434+ struct au_vdir *vdir_cache;
4a4d8108
AM
10435+ struct au_finfo *finfo;
10436+ struct au_fidir *fidir;
f0c0a007 10437+ struct au_hfile *hf;
5afbbe0d 10438+ aufs_bindex_t bindex, bbot;
1facf9fc 10439+
4a4d8108
AM
10440+ finfo = au_fi(file);
10441+ fidir = finfo->fi_hdir;
10442+ if (fidir) {
8b6a4947
AM
10443+ au_hbl_del(&finfo->fi_hlist,
10444+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108
AM
10445+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
10446+ if (vdir_cache)
1c60b727 10447+ au_vdir_free(vdir_cache);
4a4d8108
AM
10448+
10449+ bindex = finfo->fi_btop;
10450+ if (bindex >= 0) {
f0c0a007 10451+ hf = fidir->fd_hfile + bindex;
4a4d8108
AM
10452+ /*
10453+ * calls fput() instead of filp_close(),
10454+ * since no dnotify or lock for the lower file.
10455+ */
5afbbe0d 10456+ bbot = fidir->fd_bbot;
f0c0a007
AM
10457+ for (; bindex <= bbot; bindex++, hf++)
10458+ if (hf->hf_file)
1c60b727 10459+ au_hfput(hf, /*execed*/0);
4a4d8108 10460+ }
9f237c51 10461+ au_kfree_rcu(fidir);
4a4d8108 10462+ finfo->fi_hdir = NULL;
1facf9fc 10463+ }
1c60b727 10464+ au_finfo_fin(file);
1facf9fc 10465+ return 0;
10466+}
10467+
10468+/* ---------------------------------------------------------------------- */
10469+
4a4d8108
AM
10470+static int au_do_flush_dir(struct file *file, fl_owner_t id)
10471+{
10472+ int err;
5afbbe0d 10473+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
10474+ struct file *h_file;
10475+
10476+ err = 0;
5afbbe0d
AM
10477+ bbot = au_fbbot_dir(file);
10478+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
10479+ h_file = au_hf_dir(file, bindex);
10480+ if (h_file)
10481+ err = vfsub_flush(h_file, id);
10482+ }
10483+ return err;
10484+}
10485+
10486+static int aufs_flush_dir(struct file *file, fl_owner_t id)
10487+{
10488+ return au_do_flush(file, id, au_do_flush_dir);
10489+}
10490+
10491+/* ---------------------------------------------------------------------- */
10492+
1facf9fc 10493+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
10494+{
10495+ int err;
5afbbe0d 10496+ aufs_bindex_t bbot, bindex;
1facf9fc 10497+ struct inode *inode;
10498+ struct super_block *sb;
10499+
10500+ err = 0;
10501+ sb = dentry->d_sb;
5527c038 10502+ inode = d_inode(dentry);
1facf9fc 10503+ IMustLock(inode);
5afbbe0d
AM
10504+ bbot = au_dbbot(dentry);
10505+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) {
1facf9fc 10506+ struct path h_path;
1facf9fc 10507+
10508+ if (au_test_ro(sb, bindex, inode))
10509+ continue;
10510+ h_path.dentry = au_h_dptr(dentry, bindex);
10511+ if (!h_path.dentry)
10512+ continue;
1facf9fc 10513+
1facf9fc 10514+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 10515+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 10516+ }
10517+
10518+ return err;
10519+}
10520+
10521+static int au_do_fsync_dir(struct file *file, int datasync)
10522+{
10523+ int err;
5afbbe0d 10524+ aufs_bindex_t bbot, bindex;
1facf9fc 10525+ struct file *h_file;
10526+ struct super_block *sb;
10527+ struct inode *inode;
1facf9fc 10528+
521ced18 10529+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10530+ if (unlikely(err))
10531+ goto out;
10532+
c06a8ce3 10533+ inode = file_inode(file);
b912730e 10534+ sb = inode->i_sb;
5afbbe0d
AM
10535+ bbot = au_fbbot_dir(file);
10536+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108 10537+ h_file = au_hf_dir(file, bindex);
1facf9fc 10538+ if (!h_file || au_test_ro(sb, bindex, inode))
10539+ continue;
10540+
53392da6 10541+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 10542+ }
10543+
4f0767ce 10544+out:
1facf9fc 10545+ return err;
10546+}
10547+
10548+/*
10549+ * @file may be NULL
10550+ */
1e00d052
AM
10551+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
10552+ int datasync)
1facf9fc 10553+{
10554+ int err;
b752ccd1 10555+ struct dentry *dentry;
5527c038 10556+ struct inode *inode;
1facf9fc 10557+ struct super_block *sb;
1facf9fc 10558+
10559+ err = 0;
2000de60 10560+ dentry = file->f_path.dentry;
5527c038 10561+ inode = d_inode(dentry);
febd17d6 10562+ inode_lock(inode);
1facf9fc 10563+ sb = dentry->d_sb;
10564+ si_noflush_read_lock(sb);
10565+ if (file)
10566+ err = au_do_fsync_dir(file, datasync);
10567+ else {
10568+ di_write_lock_child(dentry);
10569+ err = au_do_fsync_dir_no_file(dentry, datasync);
10570+ }
5527c038 10571+ au_cpup_attr_timesizes(inode);
1facf9fc 10572+ di_write_unlock(dentry);
10573+ if (file)
10574+ fi_write_unlock(file);
10575+
10576+ si_read_unlock(sb);
febd17d6 10577+ inode_unlock(inode);
1facf9fc 10578+ return err;
10579+}
10580+
10581+/* ---------------------------------------------------------------------- */
10582+
5afbbe0d 10583+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx)
1facf9fc 10584+{
10585+ int err;
10586+ struct dentry *dentry;
9dbd164d 10587+ struct inode *inode, *h_inode;
1facf9fc 10588+ struct super_block *sb;
10589+
062440b3 10590+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 10591+
2000de60 10592+ dentry = file->f_path.dentry;
5527c038 10593+ inode = d_inode(dentry);
1facf9fc 10594+ IMustLock(inode);
10595+
10596+ sb = dentry->d_sb;
10597+ si_read_lock(sb, AuLock_FLUSH);
521ced18 10598+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10599+ if (unlikely(err))
10600+ goto out;
027c5e7a
AM
10601+ err = au_alive_dir(dentry);
10602+ if (!err)
10603+ err = au_vdir_init(file);
1facf9fc 10604+ di_downgrade_lock(dentry, AuLock_IR);
10605+ if (unlikely(err))
10606+ goto out_unlock;
10607+
5afbbe0d 10608+ h_inode = au_h_iptr(inode, au_ibtop(inode));
b752ccd1 10609+ if (!au_test_nfsd()) {
392086de 10610+ err = au_vdir_fill_de(file, ctx);
9dbd164d 10611+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 10612+ } else {
10613+ /*
10614+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
10615+ * encode_fh() and others.
10616+ */
9dbd164d 10617+ atomic_inc(&h_inode->i_count);
1facf9fc 10618+ di_read_unlock(dentry, AuLock_IR);
10619+ si_read_unlock(sb);
392086de 10620+ err = au_vdir_fill_de(file, ctx);
1facf9fc 10621+ fsstack_copy_attr_atime(inode, h_inode);
10622+ fi_write_unlock(file);
9dbd164d 10623+ iput(h_inode);
1facf9fc 10624+
10625+ AuTraceErr(err);
10626+ return err;
10627+ }
10628+
4f0767ce 10629+out_unlock:
1facf9fc 10630+ di_read_unlock(dentry, AuLock_IR);
10631+ fi_write_unlock(file);
4f0767ce 10632+out:
1facf9fc 10633+ si_read_unlock(sb);
10634+ return err;
10635+}
10636+
10637+/* ---------------------------------------------------------------------- */
10638+
10639+#define AuTestEmpty_WHONLY 1
dece6358
AM
10640+#define AuTestEmpty_CALLED (1 << 1)
10641+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 10642+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
10643+#define au_fset_testempty(flags, name) \
10644+ do { (flags) |= AuTestEmpty_##name; } while (0)
10645+#define au_fclr_testempty(flags, name) \
10646+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 10647+
dece6358
AM
10648+#ifndef CONFIG_AUFS_SHWH
10649+#undef AuTestEmpty_SHWH
10650+#define AuTestEmpty_SHWH 0
10651+#endif
10652+
1facf9fc 10653+struct test_empty_arg {
392086de 10654+ struct dir_context ctx;
1308ab2a 10655+ struct au_nhash *whlist;
1facf9fc 10656+ unsigned int flags;
10657+ int err;
10658+ aufs_bindex_t bindex;
10659+};
10660+
392086de
AM
10661+static int test_empty_cb(struct dir_context *ctx, const char *__name,
10662+ int namelen, loff_t offset __maybe_unused, u64 ino,
dece6358 10663+ unsigned int d_type)
1facf9fc 10664+{
392086de
AM
10665+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
10666+ ctx);
1facf9fc 10667+ char *name = (void *)__name;
10668+
10669+ arg->err = 0;
10670+ au_fset_testempty(arg->flags, CALLED);
10671+ /* smp_mb(); */
10672+ if (name[0] == '.'
10673+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
10674+ goto out; /* success */
10675+
10676+ if (namelen <= AUFS_WH_PFX_LEN
10677+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
10678+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 10679+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10680+ arg->err = -ENOTEMPTY;
10681+ goto out;
10682+ }
10683+
10684+ name += AUFS_WH_PFX_LEN;
10685+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 10686+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10687+ arg->err = au_nhash_append_wh
1308ab2a 10688+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 10689+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 10690+
4f0767ce 10691+out:
1facf9fc 10692+ /* smp_mb(); */
10693+ AuTraceErr(arg->err);
10694+ return arg->err;
10695+}
10696+
10697+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10698+{
10699+ int err;
10700+ struct file *h_file;
acd2b654 10701+ struct au_branch *br;
1facf9fc 10702+
10703+ h_file = au_h_open(dentry, arg->bindex,
10704+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
392086de 10705+ /*file*/NULL, /*force_wr*/0);
1facf9fc 10706+ err = PTR_ERR(h_file);
10707+ if (IS_ERR(h_file))
10708+ goto out;
10709+
10710+ err = 0;
10711+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
c06a8ce3 10712+ && !file_inode(h_file)->i_nlink)
1facf9fc 10713+ goto out_put;
10714+
10715+ do {
10716+ arg->err = 0;
10717+ au_fclr_testempty(arg->flags, CALLED);
10718+ /* smp_mb(); */
392086de 10719+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1facf9fc 10720+ if (err >= 0)
10721+ err = arg->err;
10722+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
10723+
4f0767ce 10724+out_put:
1facf9fc 10725+ fput(h_file);
acd2b654
AM
10726+ br = au_sbr(dentry->d_sb, arg->bindex);
10727+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 10728+out:
1facf9fc 10729+ return err;
10730+}
10731+
10732+struct do_test_empty_args {
10733+ int *errp;
10734+ struct dentry *dentry;
10735+ struct test_empty_arg *arg;
10736+};
10737+
10738+static void call_do_test_empty(void *args)
10739+{
10740+ struct do_test_empty_args *a = args;
10741+ *a->errp = do_test_empty(a->dentry, a->arg);
10742+}
10743+
10744+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10745+{
10746+ int err, wkq_err;
10747+ struct dentry *h_dentry;
10748+ struct inode *h_inode;
10749+
10750+ h_dentry = au_h_dptr(dentry, arg->bindex);
5527c038 10751+ h_inode = d_inode(h_dentry);
53392da6 10752+ /* todo: i_mode changes anytime? */
be118d29 10753+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 10754+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
3c1bdaff 10755+ inode_unlock_shared(h_inode);
1facf9fc 10756+ if (!err)
10757+ err = do_test_empty(dentry, arg);
10758+ else {
10759+ struct do_test_empty_args args = {
10760+ .errp = &err,
10761+ .dentry = dentry,
10762+ .arg = arg
10763+ };
10764+ unsigned int flags = arg->flags;
10765+
10766+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
10767+ if (unlikely(wkq_err))
10768+ err = wkq_err;
10769+ arg->flags = flags;
10770+ }
10771+
10772+ return err;
10773+}
10774+
10775+int au_test_empty_lower(struct dentry *dentry)
10776+{
10777+ int err;
1308ab2a 10778+ unsigned int rdhash;
5afbbe0d 10779+ aufs_bindex_t bindex, btop, btail;
1308ab2a 10780+ struct au_nhash whlist;
392086de
AM
10781+ struct test_empty_arg arg = {
10782+ .ctx = {
2000de60 10783+ .actor = test_empty_cb
392086de
AM
10784+ }
10785+ };
076b876e 10786+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg);
1facf9fc 10787+
dece6358
AM
10788+ SiMustAnyLock(dentry->d_sb);
10789+
1308ab2a 10790+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
10791+ if (!rdhash)
10792+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
10793+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 10794+ if (unlikely(err))
1facf9fc 10795+ goto out;
10796+
1facf9fc 10797+ arg.flags = 0;
1308ab2a 10798+ arg.whlist = &whlist;
5afbbe0d 10799+ btop = au_dbtop(dentry);
dece6358
AM
10800+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10801+ au_fset_testempty(arg.flags, SHWH);
076b876e
AM
10802+ test_empty = do_test_empty;
10803+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1))
10804+ test_empty = sio_test_empty;
5afbbe0d 10805+ arg.bindex = btop;
076b876e 10806+ err = test_empty(dentry, &arg);
1facf9fc 10807+ if (unlikely(err))
10808+ goto out_whlist;
10809+
10810+ au_fset_testempty(arg.flags, WHONLY);
10811+ btail = au_dbtaildir(dentry);
5afbbe0d 10812+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) {
1facf9fc 10813+ struct dentry *h_dentry;
10814+
10815+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10816+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10817+ arg.bindex = bindex;
076b876e 10818+ err = test_empty(dentry, &arg);
1facf9fc 10819+ }
10820+ }
10821+
4f0767ce 10822+out_whlist:
1308ab2a 10823+ au_nhash_wh_free(&whlist);
4f0767ce 10824+out:
1facf9fc 10825+ return err;
10826+}
10827+
10828+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
10829+{
10830+ int err;
392086de
AM
10831+ struct test_empty_arg arg = {
10832+ .ctx = {
2000de60 10833+ .actor = test_empty_cb
392086de
AM
10834+ }
10835+ };
1facf9fc 10836+ aufs_bindex_t bindex, btail;
10837+
10838+ err = 0;
1308ab2a 10839+ arg.whlist = whlist;
1facf9fc 10840+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
10841+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10842+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 10843+ btail = au_dbtaildir(dentry);
5afbbe0d 10844+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) {
1facf9fc 10845+ struct dentry *h_dentry;
10846+
10847+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10848+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10849+ arg.bindex = bindex;
10850+ err = sio_test_empty(dentry, &arg);
10851+ }
10852+ }
10853+
10854+ return err;
10855+}
10856+
10857+/* ---------------------------------------------------------------------- */
10858+
10859+const struct file_operations aufs_dir_fop = {
4a4d8108 10860+ .owner = THIS_MODULE,
027c5e7a 10861+ .llseek = default_llseek,
1facf9fc 10862+ .read = generic_read_dir,
5afbbe0d 10863+ .iterate_shared = aufs_iterate_shared,
1facf9fc 10864+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
10865+#ifdef CONFIG_COMPAT
10866+ .compat_ioctl = aufs_compat_ioctl_dir,
10867+#endif
1facf9fc 10868+ .open = aufs_open_dir,
10869+ .release = aufs_release_dir,
4a4d8108 10870+ .flush = aufs_flush_dir,
1facf9fc 10871+ .fsync = aufs_fsync_dir
10872+};
7f207e10 10873diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
eca34b5c
AM
10874--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
10875+++ linux/fs/aufs/dir.h 2019-07-11 15:42:14.462237786 +0200
9f237c51 10876@@ -0,0 +1,134 @@
062440b3 10877+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 10878+/*
ba1aed25 10879+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 10880+ *
10881+ * This program, aufs is free software; you can redistribute it and/or modify
10882+ * it under the terms of the GNU General Public License as published by
10883+ * the Free Software Foundation; either version 2 of the License, or
10884+ * (at your option) any later version.
dece6358
AM
10885+ *
10886+ * This program is distributed in the hope that it will be useful,
10887+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10888+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10889+ * GNU General Public License for more details.
10890+ *
10891+ * You should have received a copy of the GNU General Public License
523b37e3 10892+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10893+ */
10894+
10895+/*
10896+ * directory operations
10897+ */
10898+
10899+#ifndef __AUFS_DIR_H__
10900+#define __AUFS_DIR_H__
10901+
10902+#ifdef __KERNEL__
10903+
10904+#include <linux/fs.h>
1facf9fc 10905+
10906+/* ---------------------------------------------------------------------- */
10907+
10908+/* need to be faster and smaller */
10909+
10910+struct au_nhash {
dece6358
AM
10911+ unsigned int nh_num;
10912+ struct hlist_head *nh_head;
1facf9fc 10913+};
10914+
10915+struct au_vdir_destr {
10916+ unsigned char len;
10917+ unsigned char name[0];
10918+} __packed;
10919+
10920+struct au_vdir_dehstr {
10921+ struct hlist_node hash;
1c60b727 10922+ struct au_vdir_destr *str;
9f237c51 10923+ struct rcu_head rcu;
4a4d8108 10924+} ____cacheline_aligned_in_smp;
1facf9fc 10925+
10926+struct au_vdir_de {
10927+ ino_t de_ino;
10928+ unsigned char de_type;
10929+ /* caution: packed */
10930+ struct au_vdir_destr de_str;
10931+} __packed;
10932+
10933+struct au_vdir_wh {
10934+ struct hlist_node wh_hash;
dece6358
AM
10935+#ifdef CONFIG_AUFS_SHWH
10936+ ino_t wh_ino;
1facf9fc 10937+ aufs_bindex_t wh_bindex;
dece6358
AM
10938+ unsigned char wh_type;
10939+#else
10940+ aufs_bindex_t wh_bindex;
10941+#endif
10942+ /* caution: packed */
1facf9fc 10943+ struct au_vdir_destr wh_str;
10944+} __packed;
10945+
10946+union au_vdir_deblk_p {
10947+ unsigned char *deblk;
10948+ struct au_vdir_de *de;
10949+};
10950+
10951+struct au_vdir {
10952+ unsigned char **vd_deblk;
10953+ unsigned long vd_nblk;
1facf9fc 10954+ struct {
10955+ unsigned long ul;
10956+ union au_vdir_deblk_p p;
10957+ } vd_last;
10958+
be118d29 10959+ u64 vd_version;
dece6358 10960+ unsigned int vd_deblk_sz;
9f237c51
AM
10961+ unsigned long vd_jiffy;
10962+ struct rcu_head rcu;
4a4d8108 10963+} ____cacheline_aligned_in_smp;
1facf9fc 10964+
10965+/* ---------------------------------------------------------------------- */
10966+
10967+/* dir.c */
10968+extern const struct file_operations aufs_dir_fop;
10969+void au_add_nlink(struct inode *dir, struct inode *h_dir);
10970+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 10971+loff_t au_dir_size(struct file *file, struct dentry *dentry);
b912730e 10972+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc);
1facf9fc 10973+int au_test_empty_lower(struct dentry *dentry);
10974+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
10975+
10976+/* vdir.c */
1308ab2a 10977+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
10978+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
10979+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 10980+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
10981+ int limit);
dece6358
AM
10982+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
10983+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
10984+ unsigned int d_type, aufs_bindex_t bindex,
10985+ unsigned char shwh);
1c60b727 10986+void au_vdir_free(struct au_vdir *vdir);
1facf9fc 10987+int au_vdir_init(struct file *file);
392086de 10988+int au_vdir_fill_de(struct file *file, struct dir_context *ctx);
1facf9fc 10989+
10990+/* ioctl.c */
10991+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
10992+
1308ab2a 10993+#ifdef CONFIG_AUFS_RDU
10994+/* rdu.c */
10995+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10996+#ifdef CONFIG_COMPAT
10997+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
10998+ unsigned long arg);
10999+#endif
1308ab2a 11000+#else
c1595e42
JR
11001+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file,
11002+ unsigned int cmd, unsigned long arg)
b752ccd1 11003+#ifdef CONFIG_COMPAT
c1595e42
JR
11004+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file,
11005+ unsigned int cmd, unsigned long arg)
b752ccd1 11006+#endif
1308ab2a 11007+#endif
11008+
1facf9fc 11009+#endif /* __KERNEL__ */
11010+#endif /* __AUFS_DIR_H__ */
8b6a4947 11011diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c
eca34b5c
AM
11012--- /usr/share/empty/fs/aufs/dirren.c 1970-01-01 01:00:00.000000000 +0100
11013+++ linux/fs/aufs/dirren.c 2019-07-11 15:42:14.462237786 +0200
062440b3 11014@@ -0,0 +1,1316 @@
cd7a4cd9 11015+// SPDX-License-Identifier: GPL-2.0
8b6a4947 11016+/*
ba1aed25 11017+ * Copyright (C) 2017-2019 Junjiro R. Okajima
8b6a4947
AM
11018+ *
11019+ * This program, aufs is free software; you can redistribute it and/or modify
11020+ * it under the terms of the GNU General Public License as published by
11021+ * the Free Software Foundation; either version 2 of the License, or
11022+ * (at your option) any later version.
11023+ *
11024+ * This program is distributed in the hope that it will be useful,
11025+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11026+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11027+ * GNU General Public License for more details.
11028+ *
11029+ * You should have received a copy of the GNU General Public License
11030+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
11031+ */
11032+
11033+/*
acd2b654 11034+ * special handling in renaming a directory
8b6a4947
AM
11035+ * in order to support looking-up the before-renamed name on the lower readonly
11036+ * branches
11037+ */
11038+
11039+#include <linux/byteorder/generic.h>
11040+#include "aufs.h"
11041+
11042+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent)
11043+{
11044+ int idx;
11045+
11046+ idx = au_dr_ihash(ent->dr_h_ino);
11047+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx);
11048+}
11049+
11050+static int au_dr_hino_test_empty(struct au_dr_br *dr)
11051+{
11052+ int ret, i;
11053+ struct hlist_bl_head *hbl;
11054+
11055+ ret = 1;
11056+ for (i = 0; ret && i < AuDirren_NHASH; i++) {
11057+ hbl = dr->dr_h_ino + i;
11058+ hlist_bl_lock(hbl);
11059+ ret &= hlist_bl_empty(hbl);
11060+ hlist_bl_unlock(hbl);
11061+ }
11062+
11063+ return ret;
11064+}
11065+
11066+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino)
11067+{
11068+ struct au_dr_hino *found, *ent;
11069+ struct hlist_bl_head *hbl;
11070+ struct hlist_bl_node *pos;
11071+ int idx;
11072+
11073+ found = NULL;
11074+ idx = au_dr_ihash(ino);
11075+ hbl = dr->dr_h_ino + idx;
11076+ hlist_bl_lock(hbl);
11077+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
11078+ if (ent->dr_h_ino == ino) {
11079+ found = ent;
11080+ break;
11081+ }
11082+ hlist_bl_unlock(hbl);
11083+
11084+ return found;
11085+}
11086+
11087+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino,
11088+ struct au_dr_hino *add_ent)
11089+{
11090+ int found, idx;
11091+ struct hlist_bl_head *hbl;
11092+ struct hlist_bl_node *pos;
11093+ struct au_dr_hino *ent;
11094+
11095+ found = 0;
11096+ idx = au_dr_ihash(ino);
11097+ hbl = dr->dr_h_ino + idx;
11098+#if 0
11099+ {
11100+ struct hlist_bl_node *tmp;
11101+
11102+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
11103+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino);
11104+ }
11105+#endif
11106+ hlist_bl_lock(hbl);
11107+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
11108+ if (ent->dr_h_ino == ino) {
11109+ found = 1;
11110+ break;
11111+ }
11112+ if (!found && add_ent)
11113+ hlist_bl_add_head(&add_ent->dr_hnode, hbl);
11114+ hlist_bl_unlock(hbl);
11115+
11116+ if (!found && add_ent)
11117+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino);
11118+
11119+ return found;
11120+}
11121+
11122+void au_dr_hino_free(struct au_dr_br *dr)
11123+{
11124+ int i;
11125+ struct hlist_bl_head *hbl;
11126+ struct hlist_bl_node *pos, *tmp;
11127+ struct au_dr_hino *ent;
11128+
11129+ /* SiMustWriteLock(sb); */
11130+
11131+ for (i = 0; i < AuDirren_NHASH; i++) {
11132+ hbl = dr->dr_h_ino + i;
11133+ /* no spinlock since sbinfo must be write-locked */
11134+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
9f237c51 11135+ au_kfree_rcu(ent);
8b6a4947
AM
11136+ INIT_HLIST_BL_HEAD(hbl);
11137+ }
11138+}
11139+
11140+/* returns the number of inodes or an error */
11141+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br,
11142+ struct file *hinofile)
11143+{
11144+ int err, i;
11145+ ssize_t ssz;
11146+ loff_t pos, oldsize;
11147+ __be64 u64;
11148+ struct inode *hinoinode;
11149+ struct hlist_bl_head *hbl;
11150+ struct hlist_bl_node *n1, *n2;
11151+ struct au_dr_hino *ent;
11152+
11153+ SiMustWriteLock(sb);
11154+ AuDebugOn(!au_br_writable(br->br_perm));
11155+
11156+ hinoinode = file_inode(hinofile);
11157+ oldsize = i_size_read(hinoinode);
11158+
11159+ err = 0;
11160+ pos = 0;
11161+ hbl = br->br_dirren.dr_h_ino;
11162+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) {
11163+ /* no bit-lock since sbinfo must be write-locked */
11164+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) {
11165+ AuDbg("hi%llu, %pD2\n",
11166+ (unsigned long long)ent->dr_h_ino, hinofile);
11167+ u64 = cpu_to_be64(ent->dr_h_ino);
11168+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos);
11169+ if (ssz == sizeof(u64))
11170+ continue;
11171+
11172+ /* write error */
11173+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11174+ err = -ENOSPC;
11175+ if (ssz < 0)
11176+ err = ssz;
11177+ break;
11178+ }
11179+ }
11180+ /* regardless the error */
11181+ if (pos < oldsize) {
11182+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile);
11183+ AuTraceErr(err);
11184+ }
11185+
11186+ AuTraceErr(err);
11187+ return err;
11188+}
11189+
11190+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile)
11191+{
11192+ int err, hidx;
11193+ ssize_t ssz;
11194+ size_t sz, n;
11195+ loff_t pos;
11196+ uint64_t u64;
11197+ struct au_dr_hino *ent;
11198+ struct inode *hinoinode;
11199+ struct hlist_bl_head *hbl;
11200+
11201+ err = 0;
11202+ pos = 0;
11203+ hbl = dr->dr_h_ino;
11204+ hinoinode = file_inode(hinofile);
11205+ sz = i_size_read(hinoinode);
11206+ AuDebugOn(sz % sizeof(u64));
11207+ n = sz / sizeof(u64);
11208+ while (n--) {
11209+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos);
11210+ if (unlikely(ssz != sizeof(u64))) {
11211+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11212+ err = -EINVAL;
11213+ if (ssz < 0)
11214+ err = ssz;
11215+ goto out_free;
11216+ }
11217+
11218+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11219+ if (!ent) {
11220+ err = -ENOMEM;
11221+ AuTraceErr(err);
11222+ goto out_free;
11223+ }
11224+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64);
11225+ AuDbg("hi%llu, %pD2\n",
11226+ (unsigned long long)ent->dr_h_ino, hinofile);
11227+ hidx = au_dr_ihash(ent->dr_h_ino);
11228+ au_hbl_add(&ent->dr_hnode, hbl + hidx);
11229+ }
11230+ goto out; /* success */
11231+
11232+out_free:
11233+ au_dr_hino_free(dr);
11234+out:
11235+ AuTraceErr(err);
11236+ return err;
11237+}
11238+
11239+/*
11240+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not.
11241+ * @path is a switch to distinguish load and store.
11242+ */
11243+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
11244+ struct au_branch *br, const struct path *path)
11245+{
11246+ int err, flags;
11247+ unsigned char load, suspend;
11248+ struct file *hinofile;
11249+ struct au_hinode *hdir;
11250+ struct inode *dir, *delegated;
11251+ struct path hinopath;
11252+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO,
11253+ sizeof(AUFS_WH_DR_BRHINO) - 1);
11254+
11255+ AuDebugOn(bindex < 0 && !br);
11256+ AuDebugOn(bindex >= 0 && br);
11257+
11258+ err = -EINVAL;
11259+ suspend = !br;
11260+ if (suspend)
11261+ br = au_sbr(sb, bindex);
11262+ load = !!path;
11263+ if (!load) {
11264+ path = &br->br_path;
11265+ AuDebugOn(!au_br_writable(br->br_perm));
11266+ if (unlikely(!au_br_writable(br->br_perm)))
11267+ goto out;
11268+ }
11269+
11270+ hdir = NULL;
11271+ if (suspend) {
11272+ dir = d_inode(sb->s_root);
11273+ hdir = au_hinode(au_ii(dir), bindex);
11274+ dir = hdir->hi_inode;
11275+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11276+ } else {
11277+ dir = d_inode(path->dentry);
11278+ inode_lock_nested(dir, AuLsc_I_CHILD);
11279+ }
11280+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry);
11281+ err = PTR_ERR(hinopath.dentry);
11282+ if (IS_ERR(hinopath.dentry))
11283+ goto out_unlock;
11284+
11285+ err = 0;
11286+ flags = O_RDONLY;
11287+ if (load) {
11288+ if (d_is_negative(hinopath.dentry))
11289+ goto out_dput; /* success */
11290+ } else {
11291+ if (au_dr_hino_test_empty(&br->br_dirren)) {
11292+ if (d_is_positive(hinopath.dentry)) {
11293+ delegated = NULL;
11294+ err = vfsub_unlink(dir, &hinopath, &delegated,
11295+ /*force*/0);
11296+ AuTraceErr(err);
11297+ if (unlikely(err))
11298+ pr_err("ignored err %d, %pd2\n",
11299+ err, hinopath.dentry);
11300+ if (unlikely(err == -EWOULDBLOCK))
11301+ iput(delegated);
11302+ err = 0;
11303+ }
11304+ goto out_dput;
11305+ } else if (!d_is_positive(hinopath.dentry)) {
11306+ err = vfsub_create(dir, &hinopath, 0600,
11307+ /*want_excl*/false);
11308+ AuTraceErr(err);
11309+ if (unlikely(err))
11310+ goto out_dput;
11311+ }
11312+ flags = O_WRONLY;
11313+ }
11314+ hinopath.mnt = path->mnt;
11315+ hinofile = vfsub_dentry_open(&hinopath, flags);
11316+ if (suspend)
11317+ au_hn_inode_unlock(hdir);
11318+ else
11319+ inode_unlock(dir);
11320+ dput(hinopath.dentry);
11321+ AuTraceErrPtr(hinofile);
11322+ if (IS_ERR(hinofile)) {
11323+ err = PTR_ERR(hinofile);
11324+ goto out;
11325+ }
11326+
11327+ if (load)
11328+ err = au_dr_hino_load(&br->br_dirren, hinofile);
11329+ else
11330+ err = au_dr_hino_store(sb, br, hinofile);
11331+ fput(hinofile);
11332+ goto out;
11333+
11334+out_dput:
11335+ dput(hinopath.dentry);
11336+out_unlock:
11337+ if (suspend)
11338+ au_hn_inode_unlock(hdir);
11339+ else
11340+ inode_unlock(dir);
11341+out:
11342+ AuTraceErr(err);
11343+ return err;
11344+}
11345+
11346+/* ---------------------------------------------------------------------- */
11347+
11348+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path)
11349+{
11350+ int err;
11351+ struct kstatfs kstfs;
11352+ dev_t dev;
11353+ struct dentry *dentry;
11354+ struct super_block *sb;
11355+
11356+ err = vfs_statfs((void *)path, &kstfs);
11357+ AuTraceErr(err);
11358+ if (unlikely(err))
11359+ goto out;
11360+
11361+ /* todo: support for UUID */
11362+
11363+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) {
11364+ brid->type = AuBrid_FSID;
11365+ brid->fsid = kstfs.f_fsid;
11366+ } else {
11367+ dentry = path->dentry;
11368+ sb = dentry->d_sb;
11369+ dev = sb->s_dev;
11370+ if (dev) {
11371+ brid->type = AuBrid_DEV;
11372+ brid->dev = dev;
11373+ }
11374+ }
11375+
11376+out:
11377+ return err;
11378+}
11379+
11380+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
11381+ const struct path *path)
11382+{
11383+ int err, i;
11384+ struct au_dr_br *dr;
11385+ struct hlist_bl_head *hbl;
11386+
11387+ dr = &br->br_dirren;
11388+ hbl = dr->dr_h_ino;
11389+ for (i = 0; i < AuDirren_NHASH; i++, hbl++)
11390+ INIT_HLIST_BL_HEAD(hbl);
11391+
11392+ err = au_dr_brid_init(&dr->dr_brid, path);
11393+ if (unlikely(err))
11394+ goto out;
11395+
11396+ if (au_opt_test(au_mntflags(sb), DIRREN))
11397+ err = au_dr_hino(sb, /*bindex*/-1, br, path);
11398+
11399+out:
11400+ AuTraceErr(err);
11401+ return err;
11402+}
11403+
11404+int au_dr_br_fin(struct super_block *sb, struct au_branch *br)
11405+{
11406+ int err;
11407+
11408+ err = 0;
11409+ if (au_br_writable(br->br_perm))
11410+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL);
11411+ if (!err)
11412+ au_dr_hino_free(&br->br_dirren);
11413+
11414+ return err;
11415+}
11416+
11417+/* ---------------------------------------------------------------------- */
11418+
11419+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode,
11420+ char *buf, size_t sz)
11421+{
11422+ int err;
11423+ unsigned int major, minor;
11424+ char *p;
11425+
11426+ p = buf;
11427+ err = snprintf(p, sz, "%d_", brid->type);
11428+ AuDebugOn(err > sz);
11429+ p += err;
11430+ sz -= err;
11431+ switch (brid->type) {
11432+ case AuBrid_Unset:
11433+ return -EINVAL;
11434+ case AuBrid_UUID:
11435+ err = snprintf(p, sz, "%pU", brid->uuid.b);
11436+ break;
11437+ case AuBrid_FSID:
11438+ err = snprintf(p, sz, "%08x-%08x",
11439+ brid->fsid.val[0], brid->fsid.val[1]);
11440+ break;
11441+ case AuBrid_DEV:
11442+ major = MAJOR(brid->dev);
11443+ minor = MINOR(brid->dev);
11444+ if (major <= 0xff && minor <= 0xff)
11445+ err = snprintf(p, sz, "%02x%02x", major, minor);
11446+ else
11447+ err = snprintf(p, sz, "%03x:%05x", major, minor);
11448+ break;
11449+ }
11450+ AuDebugOn(err > sz);
11451+ p += err;
11452+ sz -= err;
11453+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino);
11454+ AuDebugOn(err > sz);
11455+ p += err;
11456+ sz -= err;
11457+
11458+ return p - buf;
11459+}
11460+
11461+static int au_drinfo_name(struct au_branch *br, char *name, int len)
11462+{
11463+ int rlen;
11464+ struct dentry *br_dentry;
11465+ struct inode *br_inode;
11466+
11467+ br_dentry = au_br_dentry(br);
11468+ br_inode = d_inode(br_dentry);
11469+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len);
11470+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ);
11471+ AuDebugOn(rlen > len);
11472+
11473+ return rlen;
11474+}
11475+
11476+/* ---------------------------------------------------------------------- */
11477+
11478+/*
11479+ * from the given @h_dentry, construct drinfo at @*fdata.
11480+ * when the size of @*fdata is not enough, reallocate and return new @fdata and
11481+ * @allocated.
11482+ */
11483+static int au_drinfo_construct(struct au_drinfo_fdata **fdata,
11484+ struct dentry *h_dentry,
11485+ unsigned char *allocated)
11486+{
11487+ int err, v;
11488+ struct au_drinfo_fdata *f, *p;
11489+ struct au_drinfo *drinfo;
11490+ struct inode *h_inode;
11491+ struct qstr *qname;
11492+
11493+ err = 0;
11494+ f = *fdata;
11495+ h_inode = d_inode(h_dentry);
11496+ qname = &h_dentry->d_name;
11497+ drinfo = &f->drinfo;
11498+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino);
11499+ drinfo->oldnamelen = qname->len;
11500+ if (*allocated < sizeof(*f) + qname->len) {
11501+ v = roundup_pow_of_two(*allocated + qname->len);
11502+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0);
11503+ if (unlikely(!p)) {
11504+ err = -ENOMEM;
11505+ AuTraceErr(err);
11506+ goto out;
11507+ }
11508+ f = p;
11509+ *fdata = f;
11510+ *allocated = v;
11511+ drinfo = &f->drinfo;
11512+ }
11513+ memcpy(drinfo->oldname, qname->name, qname->len);
11514+ AuDbg("i%llu, %.*s\n",
11515+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen,
11516+ drinfo->oldname);
11517+
11518+out:
11519+ AuTraceErr(err);
11520+ return err;
11521+}
11522+
11523+/* callers have to free the return value */
11524+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino)
11525+{
11526+ struct au_drinfo *ret, *drinfo;
11527+ struct au_drinfo_fdata fdata;
11528+ int len;
11529+ loff_t pos;
11530+ ssize_t ssz;
11531+
11532+ ret = ERR_PTR(-EIO);
11533+ pos = 0;
11534+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos);
11535+ if (unlikely(ssz != sizeof(fdata))) {
11536+ AuIOErr("ssz %zd, %u, %pD2\n",
11537+ ssz, (unsigned int)sizeof(fdata), file);
11538+ goto out;
11539+ }
11540+
11541+ fdata.magic = ntohl((__force __be32)fdata.magic);
11542+ switch (fdata.magic) {
11543+ case AUFS_DRINFO_MAGIC_V1:
11544+ break;
11545+ default:
11546+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n",
11547+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file);
11548+ goto out;
11549+ }
11550+
11551+ drinfo = &fdata.drinfo;
11552+ len = drinfo->oldnamelen;
11553+ if (!len) {
11554+ AuIOErr("broken drinfo %pD2\n", file);
11555+ goto out;
11556+ }
11557+
11558+ ret = NULL;
11559+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino);
11560+ if (unlikely(h_ino && drinfo->ino != h_ino)) {
11561+ AuDbg("ignored i%llu, i%llu, %pD2\n",
11562+ (unsigned long long)drinfo->ino,
11563+ (unsigned long long)h_ino, file);
11564+ goto out; /* success */
11565+ }
11566+
11567+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS);
11568+ if (unlikely(!ret)) {
11569+ ret = ERR_PTR(-ENOMEM);
11570+ AuTraceErrPtr(ret);
11571+ goto out;
11572+ }
11573+
11574+ *ret = *drinfo;
11575+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos);
11576+ if (unlikely(ssz != len)) {
9f237c51 11577+ au_kfree_rcu(ret);
8b6a4947
AM
11578+ ret = ERR_PTR(-EIO);
11579+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file);
11580+ goto out;
11581+ }
11582+
11583+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname);
11584+
11585+out:
11586+ return ret;
11587+}
11588+
11589+/* ---------------------------------------------------------------------- */
11590+
11591+/* in order to be revertible */
11592+struct au_drinfo_rev_elm {
11593+ int created;
11594+ struct dentry *info_dentry;
11595+ struct au_drinfo *info_last;
11596+};
11597+
11598+struct au_drinfo_rev {
11599+ unsigned char already;
11600+ aufs_bindex_t nelm;
11601+ struct au_drinfo_rev_elm elm[0];
11602+};
11603+
11604+/* todo: isn't it too large? */
11605+struct au_drinfo_store {
11606+ struct path h_ppath;
11607+ struct dentry *h_dentry;
11608+ struct au_drinfo_fdata *fdata;
11609+ char *infoname; /* inside of whname, just after PFX */
11610+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ];
11611+ aufs_bindex_t btgt, btail;
11612+ unsigned char no_sio,
11613+ allocated, /* current size of *fdata */
11614+ infonamelen, /* room size for p */
acd2b654 11615+ whnamelen, /* length of the generated name */
8b6a4947
AM
11616+ renameback; /* renamed back */
11617+};
11618+
11619+/* on rename(2) error, the caller should revert it using @elm */
11620+static int au_drinfo_do_store(struct au_drinfo_store *w,
11621+ struct au_drinfo_rev_elm *elm)
11622+{
11623+ int err, len;
11624+ ssize_t ssz;
11625+ loff_t pos;
11626+ struct path infopath = {
11627+ .mnt = w->h_ppath.mnt
11628+ };
11629+ struct inode *h_dir, *h_inode, *delegated;
11630+ struct file *infofile;
11631+ struct qstr *qname;
11632+
11633+ AuDebugOn(elm
11634+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm)));
11635+
11636+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry,
11637+ w->whnamelen);
11638+ AuTraceErrPtr(infopath.dentry);
11639+ if (IS_ERR(infopath.dentry)) {
11640+ err = PTR_ERR(infopath.dentry);
11641+ goto out;
11642+ }
11643+
11644+ err = 0;
11645+ h_dir = d_inode(w->h_ppath.dentry);
11646+ if (elm && d_is_negative(infopath.dentry)) {
11647+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true);
11648+ AuTraceErr(err);
11649+ if (unlikely(err))
11650+ goto out_dput;
11651+ elm->created = 1;
11652+ elm->info_dentry = dget(infopath.dentry);
11653+ }
11654+
11655+ infofile = vfsub_dentry_open(&infopath, O_RDWR);
11656+ AuTraceErrPtr(infofile);
11657+ if (IS_ERR(infofile)) {
11658+ err = PTR_ERR(infofile);
11659+ goto out_dput;
11660+ }
11661+
11662+ h_inode = d_inode(infopath.dentry);
11663+ if (elm && i_size_read(h_inode)) {
11664+ h_inode = d_inode(w->h_dentry);
11665+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino);
11666+ AuTraceErrPtr(elm->info_last);
11667+ if (IS_ERR(elm->info_last)) {
11668+ err = PTR_ERR(elm->info_last);
11669+ elm->info_last = NULL;
11670+ AuDebugOn(elm->info_dentry);
11671+ goto out_fput;
11672+ }
11673+ }
11674+
11675+ if (elm && w->renameback) {
11676+ delegated = NULL;
11677+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0);
11678+ AuTraceErr(err);
11679+ if (unlikely(err == -EWOULDBLOCK))
11680+ iput(delegated);
11681+ goto out_fput;
11682+ }
11683+
11684+ pos = 0;
11685+ qname = &w->h_dentry->d_name;
11686+ len = sizeof(*w->fdata) + qname->len;
11687+ if (!elm)
11688+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen;
11689+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos);
11690+ if (ssz == len) {
11691+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino,
11692+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname);
11693+ goto out_fput; /* success */
11694+ } else {
11695+ err = -EIO;
11696+ if (ssz < 0)
11697+ err = ssz;
11698+ /* the caller should revert it using @elm */
11699+ }
11700+
11701+out_fput:
11702+ fput(infofile);
11703+out_dput:
11704+ dput(infopath.dentry);
11705+out:
11706+ AuTraceErr(err);
11707+ return err;
11708+}
11709+
11710+struct au_call_drinfo_do_store_args {
11711+ int *errp;
11712+ struct au_drinfo_store *w;
11713+ struct au_drinfo_rev_elm *elm;
11714+};
11715+
11716+static void au_call_drinfo_do_store(void *args)
11717+{
11718+ struct au_call_drinfo_do_store_args *a = args;
11719+
11720+ *a->errp = au_drinfo_do_store(a->w, a->elm);
11721+}
11722+
11723+static int au_drinfo_store_sio(struct au_drinfo_store *w,
11724+ struct au_drinfo_rev_elm *elm)
11725+{
11726+ int err, wkq_err;
11727+
11728+ if (w->no_sio)
11729+ err = au_drinfo_do_store(w, elm);
11730+ else {
11731+ struct au_call_drinfo_do_store_args a = {
11732+ .errp = &err,
11733+ .w = w,
11734+ .elm = elm
11735+ };
11736+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a);
11737+ if (unlikely(wkq_err))
11738+ err = wkq_err;
11739+ }
11740+ AuTraceErr(err);
11741+
11742+ return err;
11743+}
11744+
11745+static int au_drinfo_store_work_init(struct au_drinfo_store *w,
11746+ aufs_bindex_t btgt)
11747+{
11748+ int err;
11749+
11750+ memset(w, 0, sizeof(*w));
11751+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40);
11752+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX);
11753+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11754+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX);
11755+ w->btgt = btgt;
11756+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
11757+
11758+ err = -ENOMEM;
11759+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS);
11760+ if (unlikely(!w->fdata)) {
11761+ AuTraceErr(err);
11762+ goto out;
11763+ }
11764+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1);
11765+ err = 0;
11766+
11767+out:
11768+ return err;
11769+}
11770+
11771+static void au_drinfo_store_work_fin(struct au_drinfo_store *w)
11772+{
9f237c51 11773+ au_kfree_rcu(w->fdata);
8b6a4947
AM
11774+}
11775+
11776+static void au_drinfo_store_rev(struct au_drinfo_rev *rev,
11777+ struct au_drinfo_store *w)
11778+{
11779+ struct au_drinfo_rev_elm *elm;
11780+ struct inode *h_dir, *delegated;
11781+ int err, nelm;
11782+ struct path infopath = {
11783+ .mnt = w->h_ppath.mnt
11784+ };
11785+
11786+ h_dir = d_inode(w->h_ppath.dentry);
11787+ IMustLock(h_dir);
11788+
11789+ err = 0;
11790+ elm = rev->elm;
11791+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11792+ AuDebugOn(elm->created && elm->info_last);
11793+ if (elm->created) {
11794+ AuDbg("here\n");
11795+ delegated = NULL;
11796+ infopath.dentry = elm->info_dentry;
11797+ err = vfsub_unlink(h_dir, &infopath, &delegated,
11798+ !w->no_sio);
11799+ AuTraceErr(err);
11800+ if (unlikely(err == -EWOULDBLOCK))
11801+ iput(delegated);
11802+ dput(elm->info_dentry);
11803+ } else if (elm->info_last) {
11804+ AuDbg("here\n");
11805+ w->fdata->drinfo = *elm->info_last;
11806+ memcpy(w->fdata->drinfo.oldname,
11807+ elm->info_last->oldname,
11808+ elm->info_last->oldnamelen);
11809+ err = au_drinfo_store_sio(w, /*elm*/NULL);
9f237c51 11810+ au_kfree_rcu(elm->info_last);
8b6a4947
AM
11811+ }
11812+ if (unlikely(err))
11813+ AuIOErr("%d, %s\n", err, w->whname);
11814+ /* go on even if err */
11815+ }
11816+}
11817+
11818+/* caller has to call au_dr_rename_fin() later */
11819+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt,
11820+ struct qstr *dst_name, void *_rev)
11821+{
11822+ int err, sz, nelm;
11823+ aufs_bindex_t bindex, btail;
11824+ struct au_drinfo_store work;
11825+ struct au_drinfo_rev *rev, **p;
11826+ struct au_drinfo_rev_elm *elm;
11827+ struct super_block *sb;
11828+ struct au_branch *br;
11829+ struct au_hinode *hdir;
11830+
11831+ err = au_drinfo_store_work_init(&work, btgt);
11832+ AuTraceErr(err);
11833+ if (unlikely(err))
11834+ goto out;
11835+
11836+ err = -ENOMEM;
11837+ btail = au_dbtaildir(dentry);
11838+ nelm = btail - btgt;
11839+ sz = sizeof(*rev) + sizeof(*elm) * nelm;
11840+ rev = kcalloc(1, sz, GFP_NOFS);
11841+ if (unlikely(!rev)) {
11842+ AuTraceErr(err);
11843+ goto out_args;
11844+ }
11845+ rev->nelm = nelm;
11846+ elm = rev->elm;
11847+ p = _rev;
11848+ *p = rev;
11849+
11850+ err = 0;
11851+ sb = dentry->d_sb;
11852+ work.h_ppath.dentry = au_h_dptr(dentry, btgt);
11853+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt);
11854+ hdir = au_hi(d_inode(dentry), btgt);
11855+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11856+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) {
11857+ work.h_dentry = au_h_dptr(dentry, bindex);
11858+ if (!work.h_dentry)
11859+ continue;
11860+
11861+ err = au_drinfo_construct(&work.fdata, work.h_dentry,
11862+ &work.allocated);
11863+ AuTraceErr(err);
11864+ if (unlikely(err))
11865+ break;
11866+
11867+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name);
11868+ br = au_sbr(sb, bindex);
11869+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11870+ work.whnamelen += au_drinfo_name(br, work.infoname,
11871+ work.infonamelen);
11872+ AuDbg("whname %.*s, i%llu, %.*s\n",
11873+ work.whnamelen, work.whname,
11874+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino),
11875+ work.fdata->drinfo.oldnamelen,
11876+ work.fdata->drinfo.oldname);
11877+
11878+ err = au_drinfo_store_sio(&work, elm);
11879+ AuTraceErr(err);
11880+ if (unlikely(err))
11881+ break;
11882+ }
11883+ if (unlikely(err)) {
11884+ /* revert all drinfo */
11885+ au_drinfo_store_rev(rev, &work);
9f237c51 11886+ au_kfree_try_rcu(rev);
8b6a4947
AM
11887+ *p = NULL;
11888+ }
11889+ au_hn_inode_unlock(hdir);
11890+
11891+out_args:
11892+ au_drinfo_store_work_fin(&work);
11893+out:
11894+ return err;
11895+}
11896+
11897+/* ---------------------------------------------------------------------- */
11898+
11899+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
11900+ struct qstr *dst_name, void *_rev)
11901+{
11902+ int err, already;
11903+ ino_t ino;
11904+ struct super_block *sb;
11905+ struct au_branch *br;
11906+ struct au_dr_br *dr;
11907+ struct dentry *h_dentry;
11908+ struct inode *h_inode;
11909+ struct au_dr_hino *ent;
11910+ struct au_drinfo_rev *rev, **p;
11911+
11912+ AuDbg("bindex %d\n", bindex);
11913+
11914+ err = -ENOMEM;
11915+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11916+ if (unlikely(!ent))
11917+ goto out;
11918+
11919+ sb = src->d_sb;
11920+ br = au_sbr(sb, bindex);
11921+ dr = &br->br_dirren;
11922+ h_dentry = au_h_dptr(src, bindex);
11923+ h_inode = d_inode(h_dentry);
11924+ ino = h_inode->i_ino;
11925+ ent->dr_h_ino = ino;
11926+ already = au_dr_hino_test_add(dr, ino, ent);
11927+ AuDbg("b%d, hi%llu, already %d\n",
11928+ bindex, (unsigned long long)ino, already);
11929+
11930+ err = au_drinfo_store(src, bindex, dst_name, _rev);
11931+ AuTraceErr(err);
11932+ if (!err) {
11933+ p = _rev;
11934+ rev = *p;
11935+ rev->already = already;
11936+ goto out; /* success */
11937+ }
11938+
11939+ /* revert */
11940+ if (!already)
11941+ au_dr_hino_del(dr, ent);
9f237c51 11942+ au_kfree_rcu(ent);
8b6a4947
AM
11943+
11944+out:
11945+ AuTraceErr(err);
11946+ return err;
11947+}
11948+
11949+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11950+{
11951+ struct au_drinfo_rev *rev;
11952+ struct au_drinfo_rev_elm *elm;
11953+ int nelm;
11954+
11955+ rev = _rev;
11956+ elm = rev->elm;
11957+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11958+ dput(elm->info_dentry);
9f237c51 11959+ au_kfree_rcu(elm->info_last);
8b6a4947 11960+ }
9f237c51 11961+ au_kfree_try_rcu(rev);
8b6a4947
AM
11962+}
11963+
11964+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11965+{
11966+ int err;
11967+ struct au_drinfo_store work;
11968+ struct au_drinfo_rev *rev = _rev;
11969+ struct super_block *sb;
11970+ struct au_branch *br;
11971+ struct inode *h_inode;
11972+ struct au_dr_br *dr;
11973+ struct au_dr_hino *ent;
11974+
11975+ err = au_drinfo_store_work_init(&work, btgt);
11976+ if (unlikely(err))
11977+ goto out;
11978+
11979+ sb = src->d_sb;
11980+ br = au_sbr(sb, btgt);
11981+ work.h_ppath.dentry = au_h_dptr(src, btgt);
11982+ work.h_ppath.mnt = au_br_mnt(br);
11983+ au_drinfo_store_rev(rev, &work);
11984+ au_drinfo_store_work_fin(&work);
11985+ if (rev->already)
11986+ goto out;
11987+
11988+ dr = &br->br_dirren;
11989+ h_inode = d_inode(work.h_ppath.dentry);
11990+ ent = au_dr_hino_find(dr, h_inode->i_ino);
11991+ BUG_ON(!ent);
11992+ au_dr_hino_del(dr, ent);
9f237c51 11993+ au_kfree_rcu(ent);
8b6a4947
AM
11994+
11995+out:
9f237c51 11996+ au_kfree_try_rcu(rev);
8b6a4947
AM
11997+ if (unlikely(err))
11998+ pr_err("failed to remove dirren info\n");
11999+}
12000+
12001+/* ---------------------------------------------------------------------- */
12002+
12003+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath,
12004+ char *whname, int whnamelen,
12005+ struct dentry **info_dentry)
12006+{
12007+ struct au_drinfo *drinfo;
12008+ struct file *f;
12009+ struct inode *h_dir;
12010+ struct path infopath;
12011+ int unlocked;
12012+
12013+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname);
12014+
12015+ *info_dentry = NULL;
12016+ drinfo = NULL;
12017+ unlocked = 0;
12018+ h_dir = d_inode(h_ppath->dentry);
be118d29 12019+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947
AM
12020+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry,
12021+ whnamelen);
12022+ if (IS_ERR(infopath.dentry)) {
12023+ drinfo = (void *)infopath.dentry;
12024+ goto out;
12025+ }
12026+
12027+ if (d_is_negative(infopath.dentry))
12028+ goto out_dput; /* success */
12029+
12030+ infopath.mnt = h_ppath->mnt;
12031+ f = vfsub_dentry_open(&infopath, O_RDONLY);
12032+ inode_unlock_shared(h_dir);
12033+ unlocked = 1;
12034+ if (IS_ERR(f)) {
12035+ drinfo = (void *)f;
12036+ goto out_dput;
12037+ }
12038+
12039+ drinfo = au_drinfo_read_k(f, /*h_ino*/0);
12040+ if (IS_ERR_OR_NULL(drinfo))
12041+ goto out_fput;
12042+
12043+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname);
12044+ *info_dentry = dget(infopath.dentry); /* keep it alive */
12045+
12046+out_fput:
12047+ fput(f);
12048+out_dput:
12049+ dput(infopath.dentry);
12050+out:
12051+ if (!unlocked)
12052+ inode_unlock_shared(h_dir);
12053+ AuTraceErrPtr(drinfo);
12054+ return drinfo;
12055+}
12056+
12057+struct au_drinfo_do_load_args {
12058+ struct au_drinfo **drinfop;
12059+ struct path *h_ppath;
12060+ char *whname;
12061+ int whnamelen;
12062+ struct dentry **info_dentry;
12063+};
12064+
12065+static void au_call_drinfo_do_load(void *args)
12066+{
12067+ struct au_drinfo_do_load_args *a = args;
12068+
12069+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen,
12070+ a->info_dentry);
12071+}
12072+
12073+struct au_drinfo_load {
12074+ struct path h_ppath;
12075+ struct qstr *qname;
12076+ unsigned char no_sio;
12077+
12078+ aufs_bindex_t ninfo;
12079+ struct au_drinfo **drinfo;
12080+};
12081+
12082+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex,
12083+ struct au_branch *br)
12084+{
12085+ int err, wkq_err, whnamelen, e;
12086+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]
12087+ = AUFS_WH_DR_INFO_PFX;
12088+ struct au_drinfo *drinfo;
12089+ struct qstr oldname;
12090+ struct inode *h_dir, *delegated;
12091+ struct dentry *info_dentry;
12092+ struct path infopath;
12093+
12094+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
12095+ whnamelen += au_drinfo_name(br, whname + whnamelen,
12096+ sizeof(whname) - whnamelen);
12097+ if (w->no_sio)
12098+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen,
12099+ &info_dentry);
12100+ else {
12101+ struct au_drinfo_do_load_args args = {
12102+ .drinfop = &drinfo,
12103+ .h_ppath = &w->h_ppath,
12104+ .whname = whname,
12105+ .whnamelen = whnamelen,
12106+ .info_dentry = &info_dentry
12107+ };
12108+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args);
12109+ if (unlikely(wkq_err))
12110+ drinfo = ERR_PTR(wkq_err);
12111+ }
12112+ err = PTR_ERR(drinfo);
12113+ if (IS_ERR_OR_NULL(drinfo))
12114+ goto out;
12115+
12116+ err = 0;
12117+ oldname.len = drinfo->oldnamelen;
12118+ oldname.name = drinfo->oldname;
12119+ if (au_qstreq(w->qname, &oldname)) {
12120+ /* the name is renamed back */
9f237c51 12121+ au_kfree_rcu(drinfo);
8b6a4947
AM
12122+ drinfo = NULL;
12123+
12124+ infopath.dentry = info_dentry;
12125+ infopath.mnt = w->h_ppath.mnt;
12126+ h_dir = d_inode(w->h_ppath.dentry);
12127+ delegated = NULL;
12128+ inode_lock_nested(h_dir, AuLsc_I_PARENT);
12129+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio);
12130+ inode_unlock(h_dir);
12131+ if (unlikely(e))
12132+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry);
12133+ if (unlikely(e == -EWOULDBLOCK))
12134+ iput(delegated);
12135+ }
9f237c51 12136+ au_kfree_rcu(w->drinfo[bindex]);
8b6a4947
AM
12137+ w->drinfo[bindex] = drinfo;
12138+ dput(info_dentry);
12139+
12140+out:
12141+ AuTraceErr(err);
12142+ return err;
12143+}
12144+
12145+/* ---------------------------------------------------------------------- */
12146+
12147+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n)
12148+{
12149+ struct au_drinfo **p = drinfo;
12150+
12151+ while (n-- > 0)
9f237c51
AM
12152+ au_kfree_rcu(*drinfo++);
12153+ au_kfree_try_rcu(p);
8b6a4947
AM
12154+}
12155+
12156+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12157+ aufs_bindex_t btgt)
12158+{
12159+ int err, ninfo;
12160+ struct au_drinfo_load w;
12161+ aufs_bindex_t bindex, bbot;
12162+ struct au_branch *br;
12163+ struct inode *h_dir;
12164+ struct au_dr_hino *ent;
12165+ struct super_block *sb;
12166+
12167+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n",
12168+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name),
12169+ AuLNPair(&lkup->whname), btgt);
12170+
12171+ sb = dentry->d_sb;
12172+ bbot = au_sbbot(sb);
12173+ w.ninfo = bbot + 1;
12174+ if (!lkup->dirren.drinfo) {
12175+ lkup->dirren.drinfo = kcalloc(w.ninfo,
12176+ sizeof(*lkup->dirren.drinfo),
12177+ GFP_NOFS);
12178+ if (unlikely(!lkup->dirren.drinfo)) {
12179+ err = -ENOMEM;
12180+ goto out;
12181+ }
12182+ lkup->dirren.ninfo = w.ninfo;
12183+ }
12184+ w.drinfo = lkup->dirren.drinfo;
12185+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
12186+ w.h_ppath.dentry = au_h_dptr(dentry, btgt);
12187+ AuDebugOn(!w.h_ppath.dentry);
12188+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt);
12189+ w.qname = &dentry->d_name;
12190+
12191+ ninfo = 0;
12192+ for (bindex = btgt + 1; bindex <= bbot; bindex++) {
12193+ br = au_sbr(sb, bindex);
12194+ err = au_drinfo_load(&w, bindex, br);
12195+ if (unlikely(err))
12196+ goto out_free;
12197+ if (w.drinfo[bindex])
12198+ ninfo++;
12199+ }
12200+ if (!ninfo) {
12201+ br = au_sbr(sb, btgt);
12202+ h_dir = d_inode(w.h_ppath.dentry);
12203+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino);
12204+ AuDebugOn(!ent);
12205+ au_dr_hino_del(&br->br_dirren, ent);
9f237c51 12206+ au_kfree_rcu(ent);
8b6a4947
AM
12207+ }
12208+ goto out; /* success */
12209+
12210+out_free:
12211+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12212+ lkup->dirren.ninfo = 0;
12213+ lkup->dirren.drinfo = NULL;
12214+out:
12215+ AuTraceErr(err);
12216+ return err;
12217+}
12218+
12219+void au_dr_lkup_fin(struct au_do_lookup_args *lkup)
12220+{
12221+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12222+}
12223+
12224+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt)
12225+{
12226+ int err;
12227+ struct au_drinfo *drinfo;
12228+
12229+ err = 0;
12230+ if (!lkup->dirren.drinfo)
12231+ goto out;
12232+ AuDebugOn(lkup->dirren.ninfo < btgt + 1);
12233+ drinfo = lkup->dirren.drinfo[btgt + 1];
12234+ if (!drinfo)
12235+ goto out;
12236+
9f237c51 12237+ au_kfree_try_rcu(lkup->whname.name);
8b6a4947
AM
12238+ lkup->whname.name = NULL;
12239+ lkup->dirren.dr_name.len = drinfo->oldnamelen;
12240+ lkup->dirren.dr_name.name = drinfo->oldname;
12241+ lkup->name = &lkup->dirren.dr_name;
12242+ err = au_wh_name_alloc(&lkup->whname, lkup->name);
12243+ if (!err)
12244+ AuDbg("name %.*s, whname %.*s, b%d\n",
12245+ AuLNPair(lkup->name), AuLNPair(&lkup->whname),
12246+ btgt);
12247+
12248+out:
12249+ AuTraceErr(err);
12250+ return err;
12251+}
12252+
12253+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12254+ ino_t h_ino)
12255+{
12256+ int match;
12257+ struct au_drinfo *drinfo;
12258+
12259+ match = 1;
12260+ if (!lkup->dirren.drinfo)
12261+ goto out;
12262+ AuDebugOn(lkup->dirren.ninfo < bindex + 1);
12263+ drinfo = lkup->dirren.drinfo[bindex + 1];
12264+ if (!drinfo)
12265+ goto out;
12266+
12267+ match = (drinfo->ino == h_ino);
12268+ AuDbg("match %d\n", match);
12269+
12270+out:
12271+ return match;
12272+}
12273+
12274+/* ---------------------------------------------------------------------- */
12275+
12276+int au_dr_opt_set(struct super_block *sb)
12277+{
12278+ int err;
12279+ aufs_bindex_t bindex, bbot;
12280+ struct au_branch *br;
12281+
12282+ err = 0;
12283+ bbot = au_sbbot(sb);
12284+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12285+ br = au_sbr(sb, bindex);
12286+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path);
12287+ }
12288+
12289+ return err;
12290+}
12291+
12292+int au_dr_opt_flush(struct super_block *sb)
12293+{
12294+ int err;
12295+ aufs_bindex_t bindex, bbot;
12296+ struct au_branch *br;
12297+
12298+ err = 0;
12299+ bbot = au_sbbot(sb);
12300+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12301+ br = au_sbr(sb, bindex);
12302+ if (au_br_writable(br->br_perm))
12303+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL);
12304+ }
12305+
12306+ return err;
12307+}
12308+
12309+int au_dr_opt_clr(struct super_block *sb, int no_flush)
12310+{
12311+ int err;
12312+ aufs_bindex_t bindex, bbot;
12313+ struct au_branch *br;
12314+
12315+ err = 0;
12316+ if (!no_flush) {
12317+ err = au_dr_opt_flush(sb);
12318+ if (unlikely(err))
12319+ goto out;
12320+ }
12321+
12322+ bbot = au_sbbot(sb);
12323+ for (bindex = 0; bindex <= bbot; bindex++) {
12324+ br = au_sbr(sb, bindex);
12325+ au_dr_hino_free(&br->br_dirren);
12326+ }
12327+
12328+out:
12329+ return err;
12330+}
12331diff -urN /usr/share/empty/fs/aufs/dirren.h linux/fs/aufs/dirren.h
eca34b5c
AM
12332--- /usr/share/empty/fs/aufs/dirren.h 1970-01-01 01:00:00.000000000 +0100
12333+++ linux/fs/aufs/dirren.h 2019-07-11 15:42:14.462237786 +0200
062440b3
AM
12334@@ -0,0 +1,140 @@
12335+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 12336+/*
ba1aed25 12337+ * Copyright (C) 2017-2019 Junjiro R. Okajima
8b6a4947
AM
12338+ *
12339+ * This program, aufs is free software; you can redistribute it and/or modify
12340+ * it under the terms of the GNU General Public License as published by
12341+ * the Free Software Foundation; either version 2 of the License, or
12342+ * (at your option) any later version.
12343+ *
12344+ * This program is distributed in the hope that it will be useful,
12345+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12346+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12347+ * GNU General Public License for more details.
12348+ *
12349+ * You should have received a copy of the GNU General Public License
12350+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
12351+ */
12352+
12353+/*
12354+ * renamed dir info
12355+ */
12356+
12357+#ifndef __AUFS_DIRREN_H__
12358+#define __AUFS_DIRREN_H__
12359+
12360+#ifdef __KERNEL__
12361+
12362+#include <linux/dcache.h>
12363+#include <linux/statfs.h>
12364+#include <linux/uuid.h>
12365+#include "hbl.h"
12366+
12367+#define AuDirren_NHASH 100
12368+
12369+#ifdef CONFIG_AUFS_DIRREN
12370+enum au_brid_type {
12371+ AuBrid_Unset,
12372+ AuBrid_UUID,
12373+ AuBrid_FSID,
12374+ AuBrid_DEV
12375+};
12376+
12377+struct au_dr_brid {
12378+ enum au_brid_type type;
12379+ union {
12380+ uuid_t uuid; /* unimplemented yet */
12381+ fsid_t fsid;
12382+ dev_t dev;
12383+ };
12384+};
12385+
12386+/* 20 is the max digits length of ulong 64 */
12387+/* brid-type "_" uuid "_" inum */
12388+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20)
12389+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20)
12390+
12391+struct au_dr_hino {
12392+ struct hlist_bl_node dr_hnode;
12393+ ino_t dr_h_ino;
12394+};
12395+
12396+struct au_dr_br {
12397+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH];
12398+ struct au_dr_brid dr_brid;
12399+};
12400+
12401+struct au_dr_lookup {
12402+ /* dr_name is pointed by struct au_do_lookup_args.name */
12403+ struct qstr dr_name; /* subset of dr_info */
12404+ aufs_bindex_t ninfo;
12405+ struct au_drinfo **drinfo;
12406+};
12407+#else
12408+struct au_dr_hino;
12409+/* empty */
12410+struct au_dr_br { };
12411+struct au_dr_lookup { };
12412+#endif
12413+
12414+/* ---------------------------------------------------------------------- */
12415+
12416+struct au_branch;
12417+struct au_do_lookup_args;
12418+struct au_hinode;
12419+#ifdef CONFIG_AUFS_DIRREN
12420+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino,
12421+ struct au_dr_hino *add_ent);
12422+void au_dr_hino_free(struct au_dr_br *dr);
12423+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
12424+ const struct path *path);
12425+int au_dr_br_fin(struct super_block *sb, struct au_branch *br);
12426+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
12427+ struct qstr *dst_name, void *_rev);
12428+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev);
12429+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev);
12430+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12431+ aufs_bindex_t bindex);
12432+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12433+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12434+ ino_t h_ino);
12435+void au_dr_lkup_fin(struct au_do_lookup_args *lkup);
12436+int au_dr_opt_set(struct super_block *sb);
12437+int au_dr_opt_flush(struct super_block *sb);
12438+int au_dr_opt_clr(struct super_block *sb, int no_flush);
12439+#else
12440+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino,
12441+ struct au_dr_hino *add_ent);
12442+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr);
12443+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br,
12444+ const struct path *path);
12445+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br);
12446+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex,
12447+ struct qstr *dst_name, void *_rev);
12448+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev);
12449+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex,
12450+ void *rev);
12451+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry,
12452+ aufs_bindex_t bindex);
12453+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12454+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup,
12455+ aufs_bindex_t bindex, ino_t h_ino);
12456+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup);
12457+AuStubInt0(au_dr_opt_set, struct super_block *sb);
12458+AuStubInt0(au_dr_opt_flush, struct super_block *sb);
12459+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush);
12460+#endif
12461+
12462+/* ---------------------------------------------------------------------- */
12463+
12464+#ifdef CONFIG_AUFS_DIRREN
12465+static inline int au_dr_ihash(ino_t h_ino)
12466+{
12467+ return h_ino % AuDirren_NHASH;
12468+}
12469+#else
12470+AuStubInt0(au_dr_ihash, ino_t h_ino);
12471+#endif
12472+
12473+#endif /* __KERNEL__ */
12474+#endif /* __AUFS_DIRREN_H__ */
7f207e10 12475diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
eca34b5c
AM
12476--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
12477+++ linux/fs/aufs/dynop.c 2019-07-11 15:42:14.465571210 +0200
fbc438ed 12478@@ -0,0 +1,367 @@
cd7a4cd9 12479+// SPDX-License-Identifier: GPL-2.0
1facf9fc 12480+/*
ba1aed25 12481+ * Copyright (C) 2010-2019 Junjiro R. Okajima
1facf9fc 12482+ *
12483+ * This program, aufs is free software; you can redistribute it and/or modify
12484+ * it under the terms of the GNU General Public License as published by
12485+ * the Free Software Foundation; either version 2 of the License, or
12486+ * (at your option) any later version.
dece6358
AM
12487+ *
12488+ * This program is distributed in the hope that it will be useful,
12489+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12490+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12491+ * GNU General Public License for more details.
12492+ *
12493+ * You should have received a copy of the GNU General Public License
523b37e3 12494+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 12495+ */
12496+
12497+/*
4a4d8108 12498+ * dynamically customizable operations for regular files
1facf9fc 12499+ */
12500+
1facf9fc 12501+#include "aufs.h"
12502+
4a4d8108 12503+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 12504+
4a4d8108
AM
12505+/*
12506+ * How large will these lists be?
12507+ * Usually just a few elements, 20-30 at most for each, I guess.
12508+ */
8b6a4947 12509+static struct hlist_bl_head dynop[AuDyLast];
4a4d8108 12510+
8b6a4947
AM
12511+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl,
12512+ const void *h_op)
1facf9fc 12513+{
4a4d8108 12514+ struct au_dykey *key, *tmp;
8b6a4947 12515+ struct hlist_bl_node *pos;
1facf9fc 12516+
4a4d8108 12517+ key = NULL;
8b6a4947
AM
12518+ hlist_bl_lock(hbl);
12519+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12520+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12521+ if (kref_get_unless_zero(&tmp->dk_kref))
12522+ key = tmp;
4a4d8108
AM
12523+ break;
12524+ }
8b6a4947 12525+ hlist_bl_unlock(hbl);
4a4d8108
AM
12526+
12527+ return key;
1facf9fc 12528+}
12529+
4a4d8108 12530+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 12531+{
4a4d8108
AM
12532+ struct au_dykey **k, *found;
12533+ const void *h_op = key->dk_op.dy_hop;
12534+ int i;
1facf9fc 12535+
4a4d8108
AM
12536+ found = NULL;
12537+ k = br->br_dykey;
12538+ for (i = 0; i < AuBrDynOp; i++)
12539+ if (k[i]) {
12540+ if (k[i]->dk_op.dy_hop == h_op) {
12541+ found = k[i];
12542+ break;
12543+ }
12544+ } else
12545+ break;
12546+ if (!found) {
12547+ spin_lock(&br->br_dykey_lock);
12548+ for (; i < AuBrDynOp; i++)
12549+ if (k[i]) {
12550+ if (k[i]->dk_op.dy_hop == h_op) {
12551+ found = k[i];
12552+ break;
12553+ }
12554+ } else {
12555+ k[i] = key;
12556+ break;
12557+ }
12558+ spin_unlock(&br->br_dykey_lock);
12559+ BUG_ON(i == AuBrDynOp); /* expand the array */
12560+ }
12561+
12562+ return found;
1facf9fc 12563+}
12564+
4a4d8108 12565+/* kref_get() if @key is already added */
8b6a4947 12566+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key)
4a4d8108
AM
12567+{
12568+ struct au_dykey *tmp, *found;
8b6a4947 12569+ struct hlist_bl_node *pos;
4a4d8108 12570+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 12571+
4a4d8108 12572+ found = NULL;
8b6a4947
AM
12573+ hlist_bl_lock(hbl);
12574+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12575+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12576+ if (kref_get_unless_zero(&tmp->dk_kref))
12577+ found = tmp;
4a4d8108
AM
12578+ break;
12579+ }
12580+ if (!found)
8b6a4947
AM
12581+ hlist_bl_add_head(&key->dk_hnode, hbl);
12582+ hlist_bl_unlock(hbl);
1facf9fc 12583+
4a4d8108
AM
12584+ if (!found)
12585+ DyPrSym(key);
12586+ return found;
12587+}
12588+
12589+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 12590+{
4a4d8108
AM
12591+ struct au_dykey *key;
12592+
12593+ key = container_of(rcu, struct au_dykey, dk_rcu);
12594+ DyPrSym(key);
83b672a5 12595+ kfree(key);
1facf9fc 12596+}
12597+
4a4d8108
AM
12598+static void dy_free(struct kref *kref)
12599+{
12600+ struct au_dykey *key;
8b6a4947 12601+ struct hlist_bl_head *hbl;
1facf9fc 12602+
4a4d8108 12603+ key = container_of(kref, struct au_dykey, dk_kref);
8b6a4947
AM
12604+ hbl = dynop + key->dk_op.dy_type;
12605+ au_hbl_del(&key->dk_hnode, hbl);
4a4d8108
AM
12606+ call_rcu(&key->dk_rcu, dy_free_rcu);
12607+}
12608+
12609+void au_dy_put(struct au_dykey *key)
1facf9fc 12610+{
4a4d8108
AM
12611+ kref_put(&key->dk_kref, dy_free);
12612+}
1facf9fc 12613+
4a4d8108
AM
12614+/* ---------------------------------------------------------------------- */
12615+
12616+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
12617+
12618+#ifdef CONFIG_AUFS_DEBUG
12619+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 12620+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
12621+#else
12622+#define DyDbgDeclare(cnt) do {} while (0)
12623+#define DyDbgInc(cnt) do {} while (0)
12624+#endif
12625+
12626+#define DySet(func, dst, src, h_op, h_sb) do { \
12627+ DyDbgInc(cnt); \
12628+ if (h_op->func) { \
12629+ if (src.func) \
12630+ dst.func = src.func; \
12631+ else \
12632+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
12633+ } \
12634+} while (0)
12635+
12636+#define DySetForce(func, dst, src) do { \
12637+ AuDebugOn(!src.func); \
12638+ DyDbgInc(cnt); \
12639+ dst.func = src.func; \
12640+} while (0)
12641+
12642+#define DySetAop(func) \
12643+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
12644+#define DySetAopForce(func) \
12645+ DySetForce(func, dyaop->da_op, aufs_aop)
12646+
12647+static void dy_aop(struct au_dykey *key, const void *h_op,
12648+ struct super_block *h_sb __maybe_unused)
12649+{
12650+ struct au_dyaop *dyaop = (void *)key;
12651+ const struct address_space_operations *h_aop = h_op;
12652+ DyDbgDeclare(cnt);
12653+
12654+ AuDbg("%s\n", au_sbtype(h_sb));
12655+
12656+ DySetAop(writepage);
12657+ DySetAopForce(readpage); /* force */
4a4d8108
AM
12658+ DySetAop(writepages);
12659+ DySetAop(set_page_dirty);
12660+ DySetAop(readpages);
12661+ DySetAop(write_begin);
12662+ DySetAop(write_end);
12663+ DySetAop(bmap);
12664+ DySetAop(invalidatepage);
12665+ DySetAop(releasepage);
027c5e7a 12666+ DySetAop(freepage);
7e9cd9fe 12667+ /* this one will be changed according to an aufs mount option */
4a4d8108 12668+ DySetAop(direct_IO);
4a4d8108 12669+ DySetAop(migratepage);
e2f27e51
AM
12670+ DySetAop(isolate_page);
12671+ DySetAop(putback_page);
4a4d8108
AM
12672+ DySetAop(launder_page);
12673+ DySetAop(is_partially_uptodate);
392086de 12674+ DySetAop(is_dirty_writeback);
4a4d8108 12675+ DySetAop(error_remove_page);
b4510431
AM
12676+ DySetAop(swap_activate);
12677+ DySetAop(swap_deactivate);
4a4d8108
AM
12678+
12679+ DyDbgSize(cnt, *h_aop);
4a4d8108
AM
12680+}
12681+
4a4d8108
AM
12682+/* ---------------------------------------------------------------------- */
12683+
12684+static void dy_bug(struct kref *kref)
12685+{
12686+ BUG();
12687+}
12688+
12689+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
12690+{
12691+ struct au_dykey *key, *old;
8b6a4947 12692+ struct hlist_bl_head *hbl;
b752ccd1 12693+ struct op {
4a4d8108 12694+ unsigned int sz;
b752ccd1
AM
12695+ void (*set)(struct au_dykey *key, const void *h_op,
12696+ struct super_block *h_sb __maybe_unused);
12697+ };
12698+ static const struct op a[] = {
4a4d8108
AM
12699+ [AuDy_AOP] = {
12700+ .sz = sizeof(struct au_dyaop),
b752ccd1 12701+ .set = dy_aop
4a4d8108 12702+ }
b752ccd1
AM
12703+ };
12704+ const struct op *p;
4a4d8108 12705+
8b6a4947
AM
12706+ hbl = dynop + op->dy_type;
12707+ key = dy_gfind_get(hbl, op->dy_hop);
4a4d8108
AM
12708+ if (key)
12709+ goto out_add; /* success */
12710+
12711+ p = a + op->dy_type;
12712+ key = kzalloc(p->sz, GFP_NOFS);
12713+ if (unlikely(!key)) {
12714+ key = ERR_PTR(-ENOMEM);
12715+ goto out;
12716+ }
12717+
12718+ key->dk_op.dy_hop = op->dy_hop;
12719+ kref_init(&key->dk_kref);
86dc4139 12720+ p->set(key, op->dy_hop, au_br_sb(br));
8b6a4947 12721+ old = dy_gadd(hbl, key);
4a4d8108 12722+ if (old) {
9f237c51 12723+ au_kfree_rcu(key);
4a4d8108
AM
12724+ key = old;
12725+ }
12726+
12727+out_add:
12728+ old = dy_bradd(br, key);
12729+ if (old)
12730+ /* its ref-count should never be zero here */
12731+ kref_put(&key->dk_kref, dy_bug);
12732+out:
12733+ return key;
12734+}
12735+
12736+/* ---------------------------------------------------------------------- */
12737+/*
acd2b654 12738+ * Aufs prohibits O_DIRECT by default even if the branch supports it.
c1595e42 12739+ * This behaviour is necessary to return an error from open(O_DIRECT) instead
4a4d8108
AM
12740+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
12741+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
12742+ * See the aufs manual in detail.
4a4d8108
AM
12743+ */
12744+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
12745+{
7e9cd9fe 12746+ if (!do_dx)
4a4d8108 12747+ dyaop->da_op.direct_IO = NULL;
7e9cd9fe 12748+ else
4a4d8108 12749+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
4a4d8108
AM
12750+}
12751+
12752+static struct au_dyaop *dy_aget(struct au_branch *br,
12753+ const struct address_space_operations *h_aop,
12754+ int do_dx)
12755+{
12756+ struct au_dyaop *dyaop;
12757+ struct au_dynop op;
12758+
12759+ op.dy_type = AuDy_AOP;
12760+ op.dy_haop = h_aop;
12761+ dyaop = (void *)dy_get(&op, br);
12762+ if (IS_ERR(dyaop))
12763+ goto out;
12764+ dy_adx(dyaop, do_dx);
12765+
12766+out:
12767+ return dyaop;
12768+}
12769+
12770+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12771+ struct inode *h_inode)
12772+{
12773+ int err, do_dx;
12774+ struct super_block *sb;
12775+ struct au_branch *br;
12776+ struct au_dyaop *dyaop;
12777+
12778+ AuDebugOn(!S_ISREG(h_inode->i_mode));
12779+ IiMustWriteLock(inode);
12780+
12781+ sb = inode->i_sb;
12782+ br = au_sbr(sb, bindex);
12783+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
12784+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
12785+ err = PTR_ERR(dyaop);
12786+ if (IS_ERR(dyaop))
12787+ /* unnecessary to call dy_fput() */
12788+ goto out;
12789+
12790+ err = 0;
12791+ inode->i_mapping->a_ops = &dyaop->da_op;
12792+
12793+out:
12794+ return err;
12795+}
12796+
b752ccd1
AM
12797+/*
12798+ * Is it safe to replace a_ops during the inode/file is in operation?
12799+ * Yes, I hope so.
12800+ */
12801+int au_dy_irefresh(struct inode *inode)
12802+{
12803+ int err;
5afbbe0d 12804+ aufs_bindex_t btop;
b752ccd1
AM
12805+ struct inode *h_inode;
12806+
12807+ err = 0;
12808+ if (S_ISREG(inode->i_mode)) {
5afbbe0d
AM
12809+ btop = au_ibtop(inode);
12810+ h_inode = au_h_iptr(inode, btop);
12811+ err = au_dy_iaop(inode, btop, h_inode);
b752ccd1
AM
12812+ }
12813+ return err;
12814+}
12815+
4a4d8108
AM
12816+void au_dy_arefresh(int do_dx)
12817+{
8b6a4947
AM
12818+ struct hlist_bl_head *hbl;
12819+ struct hlist_bl_node *pos;
4a4d8108
AM
12820+ struct au_dykey *key;
12821+
8b6a4947
AM
12822+ hbl = dynop + AuDy_AOP;
12823+ hlist_bl_lock(hbl);
12824+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode)
4a4d8108 12825+ dy_adx((void *)key, do_dx);
8b6a4947 12826+ hlist_bl_unlock(hbl);
4a4d8108
AM
12827+}
12828+
4a4d8108
AM
12829+/* ---------------------------------------------------------------------- */
12830+
12831+void __init au_dy_init(void)
12832+{
12833+ int i;
12834+
4a4d8108 12835+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12836+ INIT_HLIST_BL_HEAD(dynop + i);
4a4d8108
AM
12837+}
12838+
12839+void au_dy_fin(void)
12840+{
12841+ int i;
12842+
12843+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12844+ WARN_ON(!hlist_bl_empty(dynop + i));
4a4d8108 12845+}
7f207e10 12846diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
eca34b5c
AM
12847--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
12848+++ linux/fs/aufs/dynop.h 2019-07-11 15:42:14.465571210 +0200
fbc438ed 12849@@ -0,0 +1,77 @@
062440b3 12850+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 12851+/*
ba1aed25 12852+ * Copyright (C) 2010-2019 Junjiro R. Okajima
4a4d8108
AM
12853+ *
12854+ * This program, aufs is free software; you can redistribute it and/or modify
12855+ * it under the terms of the GNU General Public License as published by
12856+ * the Free Software Foundation; either version 2 of the License, or
12857+ * (at your option) any later version.
12858+ *
12859+ * This program is distributed in the hope that it will be useful,
12860+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12861+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12862+ * GNU General Public License for more details.
12863+ *
12864+ * You should have received a copy of the GNU General Public License
523b37e3 12865+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12866+ */
12867+
12868+/*
12869+ * dynamically customizable operations (for regular files only)
12870+ */
12871+
12872+#ifndef __AUFS_DYNOP_H__
12873+#define __AUFS_DYNOP_H__
12874+
12875+#ifdef __KERNEL__
12876+
7e9cd9fe
AM
12877+#include <linux/fs.h>
12878+#include <linux/kref.h>
4a4d8108 12879+
2cbb1c4b 12880+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
12881+
12882+struct au_dynop {
12883+ int dy_type;
12884+ union {
12885+ const void *dy_hop;
12886+ const struct address_space_operations *dy_haop;
4a4d8108
AM
12887+ };
12888+};
12889+
12890+struct au_dykey {
12891+ union {
8b6a4947 12892+ struct hlist_bl_node dk_hnode;
4a4d8108
AM
12893+ struct rcu_head dk_rcu;
12894+ };
12895+ struct au_dynop dk_op;
12896+
12897+ /*
12898+ * during I am in the branch local array, kref is gotten. when the
12899+ * branch is removed, kref is put.
12900+ */
12901+ struct kref dk_kref;
12902+};
12903+
12904+/* stop unioning since their sizes are very different from each other */
12905+struct au_dyaop {
12906+ struct au_dykey da_key;
12907+ struct address_space_operations da_op; /* not const */
4a4d8108 12908+};
fbc438ed
JR
12909+/* make sure that 'struct au_dykey *' can be any type */
12910+static_assert(!offsetof(struct au_dyaop, da_key));
4a4d8108 12911+
4a4d8108
AM
12912+/* ---------------------------------------------------------------------- */
12913+
12914+/* dynop.c */
12915+struct au_branch;
12916+void au_dy_put(struct au_dykey *key);
12917+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12918+ struct inode *h_inode);
b752ccd1 12919+int au_dy_irefresh(struct inode *inode);
4a4d8108 12920+void au_dy_arefresh(int do_dio);
4a4d8108
AM
12921+
12922+void __init au_dy_init(void);
12923+void au_dy_fin(void);
12924+
4a4d8108
AM
12925+#endif /* __KERNEL__ */
12926+#endif /* __AUFS_DYNOP_H__ */
7f207e10 12927diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
eca34b5c
AM
12928--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
12929+++ linux/fs/aufs/export.c 2019-07-11 15:42:14.465571210 +0200
062440b3 12930@@ -0,0 +1,838 @@
cd7a4cd9 12931+// SPDX-License-Identifier: GPL-2.0
4a4d8108 12932+/*
ba1aed25 12933+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
12934+ *
12935+ * This program, aufs is free software; you can redistribute it and/or modify
12936+ * it under the terms of the GNU General Public License as published by
12937+ * the Free Software Foundation; either version 2 of the License, or
12938+ * (at your option) any later version.
12939+ *
12940+ * This program is distributed in the hope that it will be useful,
12941+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12942+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12943+ * GNU General Public License for more details.
12944+ *
12945+ * You should have received a copy of the GNU General Public License
523b37e3 12946+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12947+ */
12948+
12949+/*
12950+ * export via nfs
12951+ */
12952+
12953+#include <linux/exportfs.h>
7eafdf33 12954+#include <linux/fs_struct.h>
4a4d8108
AM
12955+#include <linux/namei.h>
12956+#include <linux/nsproxy.h>
12957+#include <linux/random.h>
12958+#include <linux/writeback.h>
12959+#include "aufs.h"
12960+
12961+union conv {
12962+#ifdef CONFIG_AUFS_INO_T_64
12963+ __u32 a[2];
12964+#else
12965+ __u32 a[1];
12966+#endif
12967+ ino_t ino;
12968+};
12969+
12970+static ino_t decode_ino(__u32 *a)
12971+{
12972+ union conv u;
12973+
12974+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
12975+ u.a[0] = a[0];
12976+#ifdef CONFIG_AUFS_INO_T_64
12977+ u.a[1] = a[1];
12978+#endif
12979+ return u.ino;
12980+}
12981+
12982+static void encode_ino(__u32 *a, ino_t ino)
12983+{
12984+ union conv u;
12985+
12986+ u.ino = ino;
12987+ a[0] = u.a[0];
12988+#ifdef CONFIG_AUFS_INO_T_64
12989+ a[1] = u.a[1];
12990+#endif
12991+}
12992+
12993+/* NFS file handle */
12994+enum {
12995+ Fh_br_id,
12996+ Fh_sigen,
12997+#ifdef CONFIG_AUFS_INO_T_64
12998+ /* support 64bit inode number */
12999+ Fh_ino1,
13000+ Fh_ino2,
13001+ Fh_dir_ino1,
13002+ Fh_dir_ino2,
13003+#else
13004+ Fh_ino1,
13005+ Fh_dir_ino1,
13006+#endif
13007+ Fh_igen,
13008+ Fh_h_type,
13009+ Fh_tail,
13010+
13011+ Fh_ino = Fh_ino1,
13012+ Fh_dir_ino = Fh_dir_ino1
13013+};
13014+
13015+static int au_test_anon(struct dentry *dentry)
13016+{
027c5e7a 13017+ /* note: read d_flags without d_lock */
4a4d8108
AM
13018+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
13019+}
13020+
a2a7ad62
AM
13021+int au_test_nfsd(void)
13022+{
13023+ int ret;
13024+ struct task_struct *tsk = current;
13025+ char comm[sizeof(tsk->comm)];
13026+
13027+ ret = 0;
13028+ if (tsk->flags & PF_KTHREAD) {
13029+ get_task_comm(comm, tsk);
13030+ ret = !strcmp(comm, "nfsd");
13031+ }
13032+
13033+ return ret;
13034+}
13035+
4a4d8108
AM
13036+/* ---------------------------------------------------------------------- */
13037+/* inode generation external table */
13038+
b752ccd1 13039+void au_xigen_inc(struct inode *inode)
4a4d8108 13040+{
4a4d8108
AM
13041+ loff_t pos;
13042+ ssize_t sz;
13043+ __u32 igen;
13044+ struct super_block *sb;
13045+ struct au_sbinfo *sbinfo;
13046+
4a4d8108 13047+ sb = inode->i_sb;
b752ccd1 13048+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 13049+
b752ccd1 13050+ sbinfo = au_sbi(sb);
1facf9fc 13051+ pos = inode->i_ino;
13052+ pos *= sizeof(igen);
13053+ igen = inode->i_generation + 1;
1facf9fc 13054+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
13055+ sizeof(igen), &pos);
13056+ if (sz == sizeof(igen))
b752ccd1 13057+ return; /* success */
1facf9fc 13058+
b752ccd1 13059+ if (unlikely(sz >= 0))
1facf9fc 13060+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 13061+}
13062+
13063+int au_xigen_new(struct inode *inode)
13064+{
13065+ int err;
13066+ loff_t pos;
13067+ ssize_t sz;
13068+ struct super_block *sb;
13069+ struct au_sbinfo *sbinfo;
13070+ struct file *file;
13071+
13072+ err = 0;
13073+ /* todo: dirty, at mount time */
13074+ if (inode->i_ino == AUFS_ROOT_INO)
13075+ goto out;
13076+ sb = inode->i_sb;
dece6358 13077+ SiMustAnyLock(sb);
1facf9fc 13078+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
13079+ goto out;
13080+
13081+ err = -EFBIG;
13082+ pos = inode->i_ino;
13083+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
13084+ AuIOErr1("too large i%lld\n", pos);
13085+ goto out;
13086+ }
13087+ pos *= sizeof(inode->i_generation);
13088+
13089+ err = 0;
13090+ sbinfo = au_sbi(sb);
13091+ file = sbinfo->si_xigen;
13092+ BUG_ON(!file);
13093+
c06a8ce3 13094+ if (vfsub_f_size_read(file)
1facf9fc 13095+ < pos + sizeof(inode->i_generation)) {
13096+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
13097+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
13098+ sizeof(inode->i_generation), &pos);
13099+ } else
13100+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
13101+ sizeof(inode->i_generation), &pos);
13102+ if (sz == sizeof(inode->i_generation))
13103+ goto out; /* success */
13104+
13105+ err = sz;
13106+ if (unlikely(sz >= 0)) {
13107+ err = -EIO;
13108+ AuIOErr("xigen error (%zd)\n", sz);
13109+ }
13110+
4f0767ce 13111+out:
1facf9fc 13112+ return err;
13113+}
13114+
062440b3 13115+int au_xigen_set(struct super_block *sb, struct path *path)
1facf9fc 13116+{
13117+ int err;
13118+ struct au_sbinfo *sbinfo;
13119+ struct file *file;
13120+
dece6358
AM
13121+ SiMustWriteLock(sb);
13122+
1facf9fc 13123+ sbinfo = au_sbi(sb);
062440b3 13124+ file = au_xino_create2(sb, path, sbinfo->si_xigen);
1facf9fc 13125+ err = PTR_ERR(file);
13126+ if (IS_ERR(file))
13127+ goto out;
13128+ err = 0;
13129+ if (sbinfo->si_xigen)
13130+ fput(sbinfo->si_xigen);
13131+ sbinfo->si_xigen = file;
13132+
4f0767ce 13133+out:
062440b3 13134+ AuTraceErr(err);
1facf9fc 13135+ return err;
13136+}
13137+
13138+void au_xigen_clr(struct super_block *sb)
13139+{
13140+ struct au_sbinfo *sbinfo;
13141+
dece6358
AM
13142+ SiMustWriteLock(sb);
13143+
1facf9fc 13144+ sbinfo = au_sbi(sb);
13145+ if (sbinfo->si_xigen) {
13146+ fput(sbinfo->si_xigen);
13147+ sbinfo->si_xigen = NULL;
13148+ }
13149+}
13150+
13151+/* ---------------------------------------------------------------------- */
13152+
13153+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
13154+ ino_t dir_ino)
13155+{
13156+ struct dentry *dentry, *d;
13157+ struct inode *inode;
13158+ unsigned int sigen;
13159+
13160+ dentry = NULL;
13161+ inode = ilookup(sb, ino);
13162+ if (!inode)
13163+ goto out;
13164+
13165+ dentry = ERR_PTR(-ESTALE);
13166+ sigen = au_sigen(sb);
5afbbe0d 13167+ if (unlikely(au_is_bad_inode(inode)
1facf9fc 13168+ || IS_DEADDIR(inode)
537831f9 13169+ || sigen != au_iigen(inode, NULL)))
1facf9fc 13170+ goto out_iput;
13171+
13172+ dentry = NULL;
13173+ if (!dir_ino || S_ISDIR(inode->i_mode))
13174+ dentry = d_find_alias(inode);
13175+ else {
027c5e7a 13176+ spin_lock(&inode->i_lock);
c1595e42 13177+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 13178+ spin_lock(&d->d_lock);
1facf9fc 13179+ if (!au_test_anon(d)
5527c038 13180+ && d_inode(d->d_parent)->i_ino == dir_ino) {
027c5e7a
AM
13181+ dentry = dget_dlock(d);
13182+ spin_unlock(&d->d_lock);
1facf9fc 13183+ break;
13184+ }
027c5e7a
AM
13185+ spin_unlock(&d->d_lock);
13186+ }
13187+ spin_unlock(&inode->i_lock);
1facf9fc 13188+ }
027c5e7a 13189+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 13190+ /* need to refresh */
1facf9fc 13191+ dput(dentry);
2cbb1c4b 13192+ dentry = NULL;
1facf9fc 13193+ }
13194+
4f0767ce 13195+out_iput:
1facf9fc 13196+ iput(inode);
4f0767ce 13197+out:
2cbb1c4b 13198+ AuTraceErrPtr(dentry);
1facf9fc 13199+ return dentry;
13200+}
13201+
13202+/* ---------------------------------------------------------------------- */
13203+
13204+/* todo: dirty? */
13205+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
13206+
13207+struct au_compare_mnt_args {
13208+ /* input */
13209+ struct super_block *sb;
13210+
13211+ /* output */
13212+ struct vfsmount *mnt;
13213+};
13214+
13215+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
13216+{
13217+ struct au_compare_mnt_args *a = arg;
13218+
13219+ if (mnt->mnt_sb != a->sb)
13220+ return 0;
13221+ a->mnt = mntget(mnt);
13222+ return 1;
13223+}
13224+
1facf9fc 13225+static struct vfsmount *au_mnt_get(struct super_block *sb)
13226+{
4a4d8108 13227+ int err;
7eafdf33 13228+ struct path root;
4a4d8108
AM
13229+ struct au_compare_mnt_args args = {
13230+ .sb = sb
13231+ };
1facf9fc 13232+
7eafdf33 13233+ get_fs_root(current->fs, &root);
523b37e3 13234+ rcu_read_lock();
7eafdf33 13235+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
523b37e3 13236+ rcu_read_unlock();
7eafdf33 13237+ path_put(&root);
4a4d8108
AM
13238+ AuDebugOn(!err);
13239+ AuDebugOn(!args.mnt);
13240+ return args.mnt;
1facf9fc 13241+}
13242+
13243+struct au_nfsd_si_lock {
4a4d8108 13244+ unsigned int sigen;
027c5e7a 13245+ aufs_bindex_t bindex, br_id;
1facf9fc 13246+ unsigned char force_lock;
13247+};
13248+
027c5e7a
AM
13249+static int si_nfsd_read_lock(struct super_block *sb,
13250+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13251+{
027c5e7a 13252+ int err;
1facf9fc 13253+ aufs_bindex_t bindex;
13254+
13255+ si_read_lock(sb, AuLock_FLUSH);
13256+
13257+ /* branch id may be wrapped around */
027c5e7a 13258+ err = 0;
1facf9fc 13259+ bindex = au_br_index(sb, nsi_lock->br_id);
13260+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
13261+ goto out; /* success */
13262+
027c5e7a
AM
13263+ err = -ESTALE;
13264+ bindex = -1;
1facf9fc 13265+ if (!nsi_lock->force_lock)
13266+ si_read_unlock(sb);
1facf9fc 13267+
4f0767ce 13268+out:
027c5e7a
AM
13269+ nsi_lock->bindex = bindex;
13270+ return err;
1facf9fc 13271+}
13272+
13273+struct find_name_by_ino {
392086de 13274+ struct dir_context ctx;
1facf9fc 13275+ int called, found;
13276+ ino_t ino;
13277+ char *name;
13278+ int namelen;
13279+};
13280+
13281+static int
392086de
AM
13282+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen,
13283+ loff_t offset, u64 ino, unsigned int d_type)
1facf9fc 13284+{
392086de
AM
13285+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino,
13286+ ctx);
1facf9fc 13287+
13288+ a->called++;
13289+ if (a->ino != ino)
13290+ return 0;
13291+
13292+ memcpy(a->name, name, namelen);
13293+ a->namelen = namelen;
13294+ a->found = 1;
13295+ return 1;
13296+}
13297+
13298+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
13299+ struct au_nfsd_si_lock *nsi_lock)
13300+{
13301+ struct dentry *dentry, *parent;
13302+ struct file *file;
13303+ struct inode *dir;
392086de
AM
13304+ struct find_name_by_ino arg = {
13305+ .ctx = {
2000de60 13306+ .actor = find_name_by_ino
392086de
AM
13307+ }
13308+ };
1facf9fc 13309+ int err;
13310+
13311+ parent = path->dentry;
13312+ if (nsi_lock)
13313+ si_read_unlock(parent->d_sb);
4a4d8108 13314+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 13315+ dentry = (void *)file;
13316+ if (IS_ERR(file))
13317+ goto out;
13318+
13319+ dentry = ERR_PTR(-ENOMEM);
537831f9 13320+ arg.name = (void *)__get_free_page(GFP_NOFS);
1facf9fc 13321+ if (unlikely(!arg.name))
13322+ goto out_file;
13323+ arg.ino = ino;
13324+ arg.found = 0;
13325+ do {
13326+ arg.called = 0;
13327+ /* smp_mb(); */
392086de 13328+ err = vfsub_iterate_dir(file, &arg.ctx);
1facf9fc 13329+ } while (!err && !arg.found && arg.called);
13330+ dentry = ERR_PTR(err);
13331+ if (unlikely(err))
13332+ goto out_name;
1716fcea
AM
13333+ /* instead of ENOENT */
13334+ dentry = ERR_PTR(-ESTALE);
1facf9fc 13335+ if (!arg.found)
13336+ goto out_name;
13337+
b4510431 13338+ /* do not call vfsub_lkup_one() */
5527c038 13339+ dir = d_inode(parent);
febd17d6 13340+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen);
1facf9fc 13341+ AuTraceErrPtr(dentry);
13342+ if (IS_ERR(dentry))
13343+ goto out_name;
13344+ AuDebugOn(au_test_anon(dentry));
5527c038 13345+ if (unlikely(d_really_is_negative(dentry))) {
1facf9fc 13346+ dput(dentry);
13347+ dentry = ERR_PTR(-ENOENT);
13348+ }
13349+
4f0767ce 13350+out_name:
1c60b727 13351+ free_page((unsigned long)arg.name);
4f0767ce 13352+out_file:
1facf9fc 13353+ fput(file);
4f0767ce 13354+out:
1facf9fc 13355+ if (unlikely(nsi_lock
13356+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
13357+ if (!IS_ERR(dentry)) {
13358+ dput(dentry);
13359+ dentry = ERR_PTR(-ESTALE);
13360+ }
13361+ AuTraceErrPtr(dentry);
13362+ return dentry;
13363+}
13364+
13365+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
13366+ ino_t dir_ino,
13367+ struct au_nfsd_si_lock *nsi_lock)
13368+{
13369+ struct dentry *dentry;
13370+ struct path path;
13371+
13372+ if (dir_ino != AUFS_ROOT_INO) {
13373+ path.dentry = decode_by_ino(sb, dir_ino, 0);
13374+ dentry = path.dentry;
13375+ if (!path.dentry || IS_ERR(path.dentry))
13376+ goto out;
13377+ AuDebugOn(au_test_anon(path.dentry));
13378+ } else
13379+ path.dentry = dget(sb->s_root);
13380+
13381+ path.mnt = au_mnt_get(sb);
13382+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
13383+ path_put(&path);
13384+
4f0767ce 13385+out:
1facf9fc 13386+ AuTraceErrPtr(dentry);
13387+ return dentry;
13388+}
13389+
13390+/* ---------------------------------------------------------------------- */
13391+
13392+static int h_acceptable(void *expv, struct dentry *dentry)
13393+{
13394+ return 1;
13395+}
13396+
13397+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
13398+ char *buf, int len, struct super_block *sb)
13399+{
13400+ char *p;
13401+ int n;
13402+ struct path path;
13403+
13404+ p = d_path(h_rootpath, buf, len);
13405+ if (IS_ERR(p))
13406+ goto out;
13407+ n = strlen(p);
13408+
13409+ path.mnt = h_rootpath->mnt;
13410+ path.dentry = h_parent;
13411+ p = d_path(&path, buf, len);
13412+ if (IS_ERR(p))
13413+ goto out;
13414+ if (n != 1)
13415+ p += n;
13416+
13417+ path.mnt = au_mnt_get(sb);
13418+ path.dentry = sb->s_root;
13419+ p = d_path(&path, buf, len - strlen(p));
13420+ mntput(path.mnt);
13421+ if (IS_ERR(p))
13422+ goto out;
13423+ if (n != 1)
13424+ p[strlen(p)] = '/';
13425+
4f0767ce 13426+out:
1facf9fc 13427+ AuTraceErrPtr(p);
13428+ return p;
13429+}
13430+
13431+static
027c5e7a
AM
13432+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
13433+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13434+{
13435+ struct dentry *dentry, *h_parent, *root;
13436+ struct super_block *h_sb;
13437+ char *pathname, *p;
13438+ struct vfsmount *h_mnt;
13439+ struct au_branch *br;
13440+ int err;
13441+ struct path path;
13442+
027c5e7a 13443+ br = au_sbr(sb, nsi_lock->bindex);
86dc4139 13444+ h_mnt = au_br_mnt(br);
1facf9fc 13445+ h_sb = h_mnt->mnt_sb;
13446+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
5afbbe0d 13447+ lockdep_off();
1facf9fc 13448+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
13449+ fh_len - Fh_tail, fh[Fh_h_type],
13450+ h_acceptable, /*context*/NULL);
5afbbe0d 13451+ lockdep_on();
1facf9fc 13452+ dentry = h_parent;
13453+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
13454+ AuWarn1("%s decode_fh failed, %ld\n",
13455+ au_sbtype(h_sb), PTR_ERR(h_parent));
13456+ goto out;
13457+ }
13458+ dentry = NULL;
13459+ if (unlikely(au_test_anon(h_parent))) {
13460+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
13461+ au_sbtype(h_sb));
13462+ goto out_h_parent;
13463+ }
13464+
13465+ dentry = ERR_PTR(-ENOMEM);
13466+ pathname = (void *)__get_free_page(GFP_NOFS);
13467+ if (unlikely(!pathname))
13468+ goto out_h_parent;
13469+
13470+ root = sb->s_root;
13471+ path.mnt = h_mnt;
13472+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 13473+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 13474+ di_read_unlock(root, !AuLock_IR);
13475+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
13476+ dentry = (void *)p;
13477+ if (IS_ERR(p))
13478+ goto out_pathname;
13479+
13480+ si_read_unlock(sb);
13481+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
13482+ dentry = ERR_PTR(err);
13483+ if (unlikely(err))
13484+ goto out_relock;
13485+
13486+ dentry = ERR_PTR(-ENOENT);
13487+ AuDebugOn(au_test_anon(path.dentry));
5527c038 13488+ if (unlikely(d_really_is_negative(path.dentry)))
1facf9fc 13489+ goto out_path;
13490+
5527c038 13491+ if (ino != d_inode(path.dentry)->i_ino)
1facf9fc 13492+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
13493+ else
13494+ dentry = dget(path.dentry);
13495+
4f0767ce 13496+out_path:
1facf9fc 13497+ path_put(&path);
4f0767ce 13498+out_relock:
1facf9fc 13499+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
13500+ if (!IS_ERR(dentry)) {
13501+ dput(dentry);
13502+ dentry = ERR_PTR(-ESTALE);
13503+ }
4f0767ce 13504+out_pathname:
1c60b727 13505+ free_page((unsigned long)pathname);
4f0767ce 13506+out_h_parent:
1facf9fc 13507+ dput(h_parent);
4f0767ce 13508+out:
1facf9fc 13509+ AuTraceErrPtr(dentry);
13510+ return dentry;
13511+}
13512+
13513+/* ---------------------------------------------------------------------- */
13514+
13515+static struct dentry *
13516+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
13517+ int fh_type)
13518+{
13519+ struct dentry *dentry;
13520+ __u32 *fh = fid->raw;
027c5e7a 13521+ struct au_branch *br;
1facf9fc 13522+ ino_t ino, dir_ino;
1facf9fc 13523+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 13524+ .force_lock = 0
13525+ };
13526+
1facf9fc 13527+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
13528+ /* it should never happen, but the file handle is unreliable */
13529+ if (unlikely(fh_len < Fh_tail))
13530+ goto out;
13531+ nsi_lock.sigen = fh[Fh_sigen];
13532+ nsi_lock.br_id = fh[Fh_br_id];
13533+
1facf9fc 13534+ /* branch id may be wrapped around */
027c5e7a
AM
13535+ br = NULL;
13536+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 13537+ goto out;
13538+ nsi_lock.force_lock = 1;
13539+
13540+ /* is this inode still cached? */
13541+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
13542+ /* it should never happen */
13543+ if (unlikely(ino == AUFS_ROOT_INO))
8cdd5066 13544+ goto out_unlock;
4a4d8108 13545+
1facf9fc 13546+ dir_ino = decode_ino(fh + Fh_dir_ino);
13547+ dentry = decode_by_ino(sb, ino, dir_ino);
13548+ if (IS_ERR(dentry))
13549+ goto out_unlock;
13550+ if (dentry)
13551+ goto accept;
13552+
13553+ /* is the parent dir cached? */
027c5e7a 13554+ br = au_sbr(sb, nsi_lock.bindex);
acd2b654 13555+ au_lcnt_inc(&br->br_nfiles);
1facf9fc 13556+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
13557+ if (IS_ERR(dentry))
13558+ goto out_unlock;
13559+ if (dentry)
13560+ goto accept;
13561+
13562+ /* lookup path */
027c5e7a 13563+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 13564+ if (IS_ERR(dentry))
13565+ goto out_unlock;
13566+ if (unlikely(!dentry))
13567+ /* todo?: make it ESTALE */
13568+ goto out_unlock;
13569+
4f0767ce 13570+accept:
027c5e7a 13571+ if (!au_digen_test(dentry, au_sigen(sb))
5527c038 13572+ && d_inode(dentry)->i_generation == fh[Fh_igen])
1facf9fc 13573+ goto out_unlock; /* success */
13574+
13575+ dput(dentry);
13576+ dentry = ERR_PTR(-ESTALE);
4f0767ce 13577+out_unlock:
027c5e7a 13578+ if (br)
acd2b654 13579+ au_lcnt_dec(&br->br_nfiles);
1facf9fc 13580+ si_read_unlock(sb);
4f0767ce 13581+out:
1facf9fc 13582+ AuTraceErrPtr(dentry);
13583+ return dentry;
13584+}
13585+
13586+#if 0 /* reserved for future use */
13587+/* support subtreecheck option */
13588+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
13589+ int fh_len, int fh_type)
13590+{
13591+ struct dentry *parent;
13592+ __u32 *fh = fid->raw;
13593+ ino_t dir_ino;
13594+
13595+ dir_ino = decode_ino(fh + Fh_dir_ino);
13596+ parent = decode_by_ino(sb, dir_ino, 0);
13597+ if (IS_ERR(parent))
13598+ goto out;
13599+ if (!parent)
13600+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
13601+ dir_ino, fh, fh_len);
13602+
4f0767ce 13603+out:
1facf9fc 13604+ AuTraceErrPtr(parent);
13605+ return parent;
13606+}
13607+#endif
13608+
13609+/* ---------------------------------------------------------------------- */
13610+
0c3ec466
AM
13611+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
13612+ struct inode *dir)
1facf9fc 13613+{
13614+ int err;
0c3ec466 13615+ aufs_bindex_t bindex;
1facf9fc 13616+ struct super_block *sb, *h_sb;
0c3ec466
AM
13617+ struct dentry *dentry, *parent, *h_parent;
13618+ struct inode *h_dir;
1facf9fc 13619+ struct au_branch *br;
13620+
1facf9fc 13621+ err = -ENOSPC;
13622+ if (unlikely(*max_len <= Fh_tail)) {
13623+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
13624+ goto out;
13625+ }
13626+
13627+ err = FILEID_ROOT;
0c3ec466
AM
13628+ if (inode->i_ino == AUFS_ROOT_INO) {
13629+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
1facf9fc 13630+ goto out;
13631+ }
13632+
1facf9fc 13633+ h_parent = NULL;
0c3ec466
AM
13634+ sb = inode->i_sb;
13635+ err = si_read_lock(sb, AuLock_FLUSH);
027c5e7a
AM
13636+ if (unlikely(err))
13637+ goto out;
13638+
1facf9fc 13639+#ifdef CONFIG_AUFS_DEBUG
13640+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
13641+ AuWarn1("NFS-exporting requires xino\n");
13642+#endif
027c5e7a 13643+ err = -EIO;
0c3ec466
AM
13644+ parent = NULL;
13645+ ii_read_lock_child(inode);
5afbbe0d 13646+ bindex = au_ibtop(inode);
0c3ec466 13647+ if (!dir) {
c1595e42 13648+ dentry = d_find_any_alias(inode);
0c3ec466
AM
13649+ if (unlikely(!dentry))
13650+ goto out_unlock;
13651+ AuDebugOn(au_test_anon(dentry));
13652+ parent = dget_parent(dentry);
13653+ dput(dentry);
13654+ if (unlikely(!parent))
13655+ goto out_unlock;
5527c038
JR
13656+ if (d_really_is_positive(parent))
13657+ dir = d_inode(parent);
1facf9fc 13658+ }
0c3ec466
AM
13659+
13660+ ii_read_lock_parent(dir);
13661+ h_dir = au_h_iptr(dir, bindex);
13662+ ii_read_unlock(dir);
13663+ if (unlikely(!h_dir))
13664+ goto out_parent;
c1595e42 13665+ h_parent = d_find_any_alias(h_dir);
1facf9fc 13666+ if (unlikely(!h_parent))
0c3ec466 13667+ goto out_hparent;
1facf9fc 13668+
13669+ err = -EPERM;
13670+ br = au_sbr(sb, bindex);
86dc4139 13671+ h_sb = au_br_sb(br);
1facf9fc 13672+ if (unlikely(!h_sb->s_export_op)) {
13673+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
0c3ec466 13674+ goto out_hparent;
1facf9fc 13675+ }
13676+
13677+ fh[Fh_br_id] = br->br_id;
13678+ fh[Fh_sigen] = au_sigen(sb);
13679+ encode_ino(fh + Fh_ino, inode->i_ino);
0c3ec466 13680+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
1facf9fc 13681+ fh[Fh_igen] = inode->i_generation;
13682+
13683+ *max_len -= Fh_tail;
13684+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
13685+ max_len,
13686+ /*connectable or subtreecheck*/0);
13687+ err = fh[Fh_h_type];
13688+ *max_len += Fh_tail;
13689+ /* todo: macros? */
1716fcea 13690+ if (err != FILEID_INVALID)
1facf9fc 13691+ err = 99;
13692+ else
13693+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
13694+
0c3ec466 13695+out_hparent:
1facf9fc 13696+ dput(h_parent);
0c3ec466 13697+out_parent:
1facf9fc 13698+ dput(parent);
0c3ec466
AM
13699+out_unlock:
13700+ ii_read_unlock(inode);
13701+ si_read_unlock(sb);
4f0767ce 13702+out:
1facf9fc 13703+ if (unlikely(err < 0))
1716fcea 13704+ err = FILEID_INVALID;
1facf9fc 13705+ return err;
13706+}
13707+
13708+/* ---------------------------------------------------------------------- */
13709+
4a4d8108
AM
13710+static int aufs_commit_metadata(struct inode *inode)
13711+{
13712+ int err;
13713+ aufs_bindex_t bindex;
13714+ struct super_block *sb;
13715+ struct inode *h_inode;
13716+ int (*f)(struct inode *inode);
13717+
13718+ sb = inode->i_sb;
e49829fe 13719+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 13720+ ii_write_lock_child(inode);
5afbbe0d 13721+ bindex = au_ibtop(inode);
4a4d8108
AM
13722+ AuDebugOn(bindex < 0);
13723+ h_inode = au_h_iptr(inode, bindex);
13724+
13725+ f = h_inode->i_sb->s_export_op->commit_metadata;
13726+ if (f)
13727+ err = f(h_inode);
13728+ else {
13729+ struct writeback_control wbc = {
13730+ .sync_mode = WB_SYNC_ALL,
13731+ .nr_to_write = 0 /* metadata only */
13732+ };
13733+
13734+ err = sync_inode(h_inode, &wbc);
13735+ }
13736+
13737+ au_cpup_attr_timesizes(inode);
13738+ ii_write_unlock(inode);
13739+ si_read_unlock(sb);
13740+ return err;
13741+}
13742+
13743+/* ---------------------------------------------------------------------- */
13744+
1facf9fc 13745+static struct export_operations aufs_export_op = {
4a4d8108 13746+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 13747+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
13748+ .encode_fh = aufs_encode_fh,
13749+ .commit_metadata = aufs_commit_metadata
1facf9fc 13750+};
13751+
13752+void au_export_init(struct super_block *sb)
13753+{
13754+ struct au_sbinfo *sbinfo;
13755+ __u32 u;
13756+
5afbbe0d
AM
13757+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS)
13758+ && IS_MODULE(CONFIG_EXPORTFS),
13759+ AUFS_NAME ": unsupported configuration "
13760+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y");
13761+
1facf9fc 13762+ sb->s_export_op = &aufs_export_op;
13763+ sbinfo = au_sbi(sb);
13764+ sbinfo->si_xigen = NULL;
13765+ get_random_bytes(&u, sizeof(u));
13766+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
13767+ atomic_set(&sbinfo->si_xigen_next, u);
13768+}
076b876e 13769diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
eca34b5c
AM
13770--- /usr/share/empty/fs/aufs/fhsm.c 1970-01-01 01:00:00.000000000 +0100
13771+++ linux/fs/aufs/fhsm.c 2019-07-11 15:42:14.465571210 +0200
062440b3 13772@@ -0,0 +1,427 @@
cd7a4cd9 13773+// SPDX-License-Identifier: GPL-2.0
076b876e 13774+/*
ba1aed25 13775+ * Copyright (C) 2011-2019 Junjiro R. Okajima
076b876e
AM
13776+ *
13777+ * This program, aufs is free software; you can redistribute it and/or modify
13778+ * it under the terms of the GNU General Public License as published by
13779+ * the Free Software Foundation; either version 2 of the License, or
13780+ * (at your option) any later version.
13781+ *
13782+ * This program is distributed in the hope that it will be useful,
13783+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13784+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13785+ * GNU General Public License for more details.
13786+ *
13787+ * You should have received a copy of the GNU General Public License
13788+ * along with this program; if not, write to the Free Software
13789+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13790+ */
13791+
13792+/*
13793+ * File-based Hierarchy Storage Management
13794+ */
13795+
13796+#include <linux/anon_inodes.h>
13797+#include <linux/poll.h>
13798+#include <linux/seq_file.h>
13799+#include <linux/statfs.h>
13800+#include "aufs.h"
13801+
c1595e42
JR
13802+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb)
13803+{
13804+ struct au_sbinfo *sbinfo;
13805+ struct au_fhsm *fhsm;
13806+
13807+ SiMustAnyLock(sb);
13808+
13809+ sbinfo = au_sbi(sb);
13810+ fhsm = &sbinfo->si_fhsm;
13811+ AuDebugOn(!fhsm);
13812+ return fhsm->fhsm_bottom;
13813+}
13814+
13815+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex)
13816+{
13817+ struct au_sbinfo *sbinfo;
13818+ struct au_fhsm *fhsm;
13819+
13820+ SiMustWriteLock(sb);
13821+
13822+ sbinfo = au_sbi(sb);
13823+ fhsm = &sbinfo->si_fhsm;
13824+ AuDebugOn(!fhsm);
13825+ fhsm->fhsm_bottom = bindex;
13826+}
13827+
13828+/* ---------------------------------------------------------------------- */
13829+
076b876e
AM
13830+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br)
13831+{
13832+ struct au_br_fhsm *bf;
13833+
13834+ bf = br->br_fhsm;
13835+ MtxMustLock(&bf->bf_lock);
13836+
13837+ return !bf->bf_readable
13838+ || time_after(jiffies,
13839+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire);
13840+}
13841+
13842+/* ---------------------------------------------------------------------- */
13843+
13844+static void au_fhsm_notify(struct super_block *sb, int val)
13845+{
13846+ struct au_sbinfo *sbinfo;
13847+ struct au_fhsm *fhsm;
13848+
13849+ SiMustAnyLock(sb);
13850+
13851+ sbinfo = au_sbi(sb);
13852+ fhsm = &sbinfo->si_fhsm;
13853+ if (au_fhsm_pid(fhsm)
13854+ && atomic_read(&fhsm->fhsm_readable) != -1) {
13855+ atomic_set(&fhsm->fhsm_readable, val);
13856+ if (val)
13857+ wake_up(&fhsm->fhsm_wqh);
13858+ }
13859+}
13860+
13861+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex,
13862+ struct aufs_stfs *rstfs, int do_lock, int do_notify)
13863+{
13864+ int err;
13865+ struct au_branch *br;
13866+ struct au_br_fhsm *bf;
13867+
13868+ br = au_sbr(sb, bindex);
13869+ AuDebugOn(au_br_rdonly(br));
13870+ bf = br->br_fhsm;
13871+ AuDebugOn(!bf);
13872+
13873+ if (do_lock)
13874+ mutex_lock(&bf->bf_lock);
13875+ else
13876+ MtxMustLock(&bf->bf_lock);
13877+
13878+ /* sb->s_root for NFS is unreliable */
13879+ err = au_br_stfs(br, &bf->bf_stfs);
13880+ if (unlikely(err)) {
13881+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err);
13882+ goto out;
13883+ }
13884+
13885+ bf->bf_jiffy = jiffies;
13886+ bf->bf_readable = 1;
13887+ if (do_notify)
13888+ au_fhsm_notify(sb, /*val*/1);
13889+ if (rstfs)
13890+ *rstfs = bf->bf_stfs;
13891+
13892+out:
13893+ if (do_lock)
13894+ mutex_unlock(&bf->bf_lock);
13895+ au_fhsm_notify(sb, /*val*/1);
13896+
13897+ return err;
13898+}
13899+
13900+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
13901+{
13902+ int err;
076b876e
AM
13903+ struct au_sbinfo *sbinfo;
13904+ struct au_fhsm *fhsm;
13905+ struct au_branch *br;
13906+ struct au_br_fhsm *bf;
13907+
13908+ AuDbg("b%d, force %d\n", bindex, force);
13909+ SiMustAnyLock(sb);
13910+
13911+ sbinfo = au_sbi(sb);
13912+ fhsm = &sbinfo->si_fhsm;
c1595e42
JR
13913+ if (!au_ftest_si(sbinfo, FHSM)
13914+ || fhsm->fhsm_bottom == bindex)
076b876e
AM
13915+ return;
13916+
13917+ br = au_sbr(sb, bindex);
13918+ bf = br->br_fhsm;
13919+ AuDebugOn(!bf);
13920+ mutex_lock(&bf->bf_lock);
13921+ if (force
13922+ || au_fhsm_pid(fhsm)
13923+ || au_fhsm_test_jiffy(sbinfo, br))
13924+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0,
13925+ /*do_notify*/1);
13926+ mutex_unlock(&bf->bf_lock);
13927+}
13928+
13929+void au_fhsm_wrote_all(struct super_block *sb, int force)
13930+{
5afbbe0d 13931+ aufs_bindex_t bindex, bbot;
076b876e
AM
13932+ struct au_branch *br;
13933+
13934+ /* exclude the bottom */
5afbbe0d
AM
13935+ bbot = au_fhsm_bottom(sb);
13936+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
13937+ br = au_sbr(sb, bindex);
13938+ if (au_br_fhsm(br->br_perm))
13939+ au_fhsm_wrote(sb, bindex, force);
13940+ }
13941+}
13942+
13943+/* ---------------------------------------------------------------------- */
13944+
be118d29 13945+static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait)
076b876e 13946+{
be118d29 13947+ __poll_t mask;
076b876e
AM
13948+ struct au_sbinfo *sbinfo;
13949+ struct au_fhsm *fhsm;
13950+
13951+ mask = 0;
13952+ sbinfo = file->private_data;
13953+ fhsm = &sbinfo->si_fhsm;
13954+ poll_wait(file, &fhsm->fhsm_wqh, wait);
13955+ if (atomic_read(&fhsm->fhsm_readable))
be118d29 13956+ mask = EPOLLIN /* | EPOLLRDNORM */;
076b876e 13957+
b00004a5
AM
13958+ if (!mask)
13959+ AuDbg("mask 0x%x\n", mask);
076b876e
AM
13960+ return mask;
13961+}
13962+
13963+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr,
13964+ struct aufs_stfs *stfs, __s16 brid)
13965+{
13966+ int err;
13967+
13968+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs));
13969+ if (!err)
13970+ err = __put_user(brid, &stbr->brid);
13971+ if (unlikely(err))
13972+ err = -EFAULT;
13973+
13974+ return err;
13975+}
13976+
13977+static ssize_t au_fhsm_do_read(struct super_block *sb,
13978+ struct aufs_stbr __user *stbr, size_t count)
13979+{
13980+ ssize_t err;
13981+ int nstbr;
5afbbe0d 13982+ aufs_bindex_t bindex, bbot;
076b876e
AM
13983+ struct au_branch *br;
13984+ struct au_br_fhsm *bf;
13985+
13986+ /* except the bottom branch */
13987+ err = 0;
13988+ nstbr = 0;
5afbbe0d
AM
13989+ bbot = au_fhsm_bottom(sb);
13990+ for (bindex = 0; !err && bindex < bbot; bindex++) {
076b876e
AM
13991+ br = au_sbr(sb, bindex);
13992+ if (!au_br_fhsm(br->br_perm))
13993+ continue;
13994+
13995+ bf = br->br_fhsm;
13996+ mutex_lock(&bf->bf_lock);
13997+ if (bf->bf_readable) {
13998+ err = -EFAULT;
13999+ if (count >= sizeof(*stbr))
14000+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs,
14001+ br->br_id);
14002+ if (!err) {
14003+ bf->bf_readable = 0;
14004+ count -= sizeof(*stbr);
14005+ nstbr++;
14006+ }
14007+ }
14008+ mutex_unlock(&bf->bf_lock);
14009+ }
14010+ if (!err)
14011+ err = sizeof(*stbr) * nstbr;
14012+
14013+ return err;
14014+}
14015+
14016+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count,
14017+ loff_t *pos)
14018+{
14019+ ssize_t err;
14020+ int readable;
5afbbe0d 14021+ aufs_bindex_t nfhsm, bindex, bbot;
076b876e
AM
14022+ struct au_sbinfo *sbinfo;
14023+ struct au_fhsm *fhsm;
14024+ struct au_branch *br;
14025+ struct super_block *sb;
14026+
14027+ err = 0;
14028+ sbinfo = file->private_data;
14029+ fhsm = &sbinfo->si_fhsm;
14030+need_data:
14031+ spin_lock_irq(&fhsm->fhsm_wqh.lock);
14032+ if (!atomic_read(&fhsm->fhsm_readable)) {
14033+ if (vfsub_file_flags(file) & O_NONBLOCK)
14034+ err = -EAGAIN;
14035+ else
14036+ err = wait_event_interruptible_locked_irq
14037+ (fhsm->fhsm_wqh,
14038+ atomic_read(&fhsm->fhsm_readable));
14039+ }
14040+ spin_unlock_irq(&fhsm->fhsm_wqh.lock);
14041+ if (unlikely(err))
14042+ goto out;
14043+
14044+ /* sb may already be dead */
14045+ au_rw_read_lock(&sbinfo->si_rwsem);
14046+ readable = atomic_read(&fhsm->fhsm_readable);
14047+ if (readable > 0) {
14048+ sb = sbinfo->si_sb;
14049+ AuDebugOn(!sb);
14050+ /* exclude the bottom branch */
14051+ nfhsm = 0;
5afbbe0d
AM
14052+ bbot = au_fhsm_bottom(sb);
14053+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
14054+ br = au_sbr(sb, bindex);
14055+ if (au_br_fhsm(br->br_perm))
14056+ nfhsm++;
14057+ }
14058+ err = -EMSGSIZE;
14059+ if (nfhsm * sizeof(struct aufs_stbr) <= count) {
14060+ atomic_set(&fhsm->fhsm_readable, 0);
14061+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf,
14062+ count);
14063+ }
14064+ }
14065+ au_rw_read_unlock(&sbinfo->si_rwsem);
14066+ if (!readable)
14067+ goto need_data;
14068+
14069+out:
14070+ return err;
14071+}
14072+
14073+static int au_fhsm_release(struct inode *inode, struct file *file)
14074+{
14075+ struct au_sbinfo *sbinfo;
14076+ struct au_fhsm *fhsm;
14077+
14078+ /* sb may already be dead */
14079+ sbinfo = file->private_data;
14080+ fhsm = &sbinfo->si_fhsm;
14081+ spin_lock(&fhsm->fhsm_spin);
14082+ fhsm->fhsm_pid = 0;
14083+ spin_unlock(&fhsm->fhsm_spin);
14084+ kobject_put(&sbinfo->si_kobj);
14085+
14086+ return 0;
14087+}
14088+
14089+static const struct file_operations au_fhsm_fops = {
14090+ .owner = THIS_MODULE,
14091+ .llseek = noop_llseek,
14092+ .read = au_fhsm_read,
14093+ .poll = au_fhsm_poll,
14094+ .release = au_fhsm_release
14095+};
14096+
14097+int au_fhsm_fd(struct super_block *sb, int oflags)
14098+{
14099+ int err, fd;
14100+ struct au_sbinfo *sbinfo;
14101+ struct au_fhsm *fhsm;
14102+
14103+ err = -EPERM;
14104+ if (unlikely(!capable(CAP_SYS_ADMIN)))
14105+ goto out;
14106+
14107+ err = -EINVAL;
14108+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK)))
14109+ goto out;
14110+
14111+ err = 0;
14112+ sbinfo = au_sbi(sb);
14113+ fhsm = &sbinfo->si_fhsm;
14114+ spin_lock(&fhsm->fhsm_spin);
14115+ if (!fhsm->fhsm_pid)
14116+ fhsm->fhsm_pid = current->pid;
14117+ else
14118+ err = -EBUSY;
14119+ spin_unlock(&fhsm->fhsm_spin);
14120+ if (unlikely(err))
14121+ goto out;
14122+
14123+ oflags |= O_RDONLY;
14124+ /* oflags |= FMODE_NONOTIFY; */
14125+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags);
14126+ err = fd;
14127+ if (unlikely(fd < 0))
14128+ goto out_pid;
14129+
acd2b654 14130+ /* succeed regardless 'fhsm' status */
076b876e
AM
14131+ kobject_get(&sbinfo->si_kobj);
14132+ si_noflush_read_lock(sb);
14133+ if (au_ftest_si(sbinfo, FHSM))
14134+ au_fhsm_wrote_all(sb, /*force*/0);
14135+ si_read_unlock(sb);
14136+ goto out; /* success */
14137+
14138+out_pid:
14139+ spin_lock(&fhsm->fhsm_spin);
14140+ fhsm->fhsm_pid = 0;
14141+ spin_unlock(&fhsm->fhsm_spin);
14142+out:
14143+ AuTraceErr(err);
14144+ return err;
14145+}
14146+
14147+/* ---------------------------------------------------------------------- */
14148+
14149+int au_fhsm_br_alloc(struct au_branch *br)
14150+{
14151+ int err;
14152+
14153+ err = 0;
14154+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS);
14155+ if (br->br_fhsm)
14156+ au_br_fhsm_init(br->br_fhsm);
14157+ else
14158+ err = -ENOMEM;
14159+
14160+ return err;
14161+}
14162+
14163+/* ---------------------------------------------------------------------- */
14164+
14165+void au_fhsm_fin(struct super_block *sb)
14166+{
14167+ au_fhsm_notify(sb, /*val*/-1);
14168+}
14169+
14170+void au_fhsm_init(struct au_sbinfo *sbinfo)
14171+{
14172+ struct au_fhsm *fhsm;
14173+
14174+ fhsm = &sbinfo->si_fhsm;
14175+ spin_lock_init(&fhsm->fhsm_spin);
14176+ init_waitqueue_head(&fhsm->fhsm_wqh);
14177+ atomic_set(&fhsm->fhsm_readable, 0);
14178+ fhsm->fhsm_expire
14179+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC);
c1595e42 14180+ fhsm->fhsm_bottom = -1;
076b876e
AM
14181+}
14182+
14183+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec)
14184+{
14185+ sbinfo->si_fhsm.fhsm_expire
14186+ = msecs_to_jiffies(sec * MSEC_PER_SEC);
14187+}
14188+
14189+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo)
14190+{
14191+ unsigned int u;
14192+
14193+ if (!au_ftest_si(sbinfo, FHSM))
14194+ return;
14195+
14196+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC;
14197+ if (u != AUFS_FHSM_CACHE_DEF_SEC)
14198+ seq_printf(seq, ",fhsm_sec=%u", u);
14199+}
7f207e10 14200diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
eca34b5c
AM
14201--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
14202+++ linux/fs/aufs/file.c 2019-07-11 15:42:14.465571210 +0200
acd2b654 14203@@ -0,0 +1,863 @@
cd7a4cd9 14204+// SPDX-License-Identifier: GPL-2.0
1facf9fc 14205+/*
ba1aed25 14206+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 14207+ *
14208+ * This program, aufs is free software; you can redistribute it and/or modify
14209+ * it under the terms of the GNU General Public License as published by
14210+ * the Free Software Foundation; either version 2 of the License, or
14211+ * (at your option) any later version.
dece6358
AM
14212+ *
14213+ * This program is distributed in the hope that it will be useful,
14214+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14215+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14216+ * GNU General Public License for more details.
14217+ *
14218+ * You should have received a copy of the GNU General Public License
523b37e3 14219+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 14220+ */
14221+
14222+/*
4a4d8108 14223+ * handling file/dir, and address_space operation
1facf9fc 14224+ */
14225+
7eafdf33
AM
14226+#ifdef CONFIG_AUFS_DEBUG
14227+#include <linux/migrate.h>
14228+#endif
4a4d8108 14229+#include <linux/pagemap.h>
1facf9fc 14230+#include "aufs.h"
14231+
4a4d8108
AM
14232+/* drop flags for writing */
14233+unsigned int au_file_roflags(unsigned int flags)
14234+{
14235+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
14236+ flags |= O_RDONLY | O_NOATIME;
14237+ return flags;
14238+}
14239+
14240+/* common functions to regular file and dir */
14241+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 14242+ struct file *file, int force_wr)
1facf9fc 14243+{
1308ab2a 14244+ struct file *h_file;
4a4d8108
AM
14245+ struct dentry *h_dentry;
14246+ struct inode *h_inode;
14247+ struct super_block *sb;
14248+ struct au_branch *br;
14249+ struct path h_path;
b912730e 14250+ int err;
1facf9fc 14251+
4a4d8108
AM
14252+ /* a race condition can happen between open and unlink/rmdir */
14253+ h_file = ERR_PTR(-ENOENT);
14254+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 14255+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry)))
4a4d8108 14256+ goto out;
5527c038 14257+ h_inode = d_inode(h_dentry);
027c5e7a
AM
14258+ spin_lock(&h_dentry->d_lock);
14259+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
5527c038 14260+ /* || !d_inode(dentry)->i_nlink */
027c5e7a
AM
14261+ ;
14262+ spin_unlock(&h_dentry->d_lock);
14263+ if (unlikely(err))
4a4d8108 14264+ goto out;
1facf9fc 14265+
4a4d8108
AM
14266+ sb = dentry->d_sb;
14267+ br = au_sbr(sb, bindex);
b912730e
AM
14268+ err = au_br_test_oflag(flags, br);
14269+ h_file = ERR_PTR(err);
14270+ if (unlikely(err))
027c5e7a 14271+ goto out;
1facf9fc 14272+
4a4d8108 14273+ /* drop flags for writing */
5527c038 14274+ if (au_test_ro(sb, bindex, d_inode(dentry))) {
392086de
AM
14275+ if (force_wr && !(flags & O_WRONLY))
14276+ force_wr = 0;
4a4d8108 14277+ flags = au_file_roflags(flags);
392086de
AM
14278+ if (force_wr) {
14279+ h_file = ERR_PTR(-EROFS);
14280+ flags = au_file_roflags(flags);
14281+ if (unlikely(vfsub_native_ro(h_inode)
14282+ || IS_APPEND(h_inode)))
14283+ goto out;
14284+ flags &= ~O_ACCMODE;
14285+ flags |= O_WRONLY;
14286+ }
14287+ }
4a4d8108 14288+ flags &= ~O_CREAT;
acd2b654 14289+ au_lcnt_inc(&br->br_nfiles);
4a4d8108 14290+ h_path.dentry = h_dentry;
86dc4139 14291+ h_path.mnt = au_br_mnt(br);
38d290e6 14292+ h_file = vfsub_dentry_open(&h_path, flags);
4a4d8108
AM
14293+ if (IS_ERR(h_file))
14294+ goto out_br;
dece6358 14295+
b912730e 14296+ if (flags & __FMODE_EXEC) {
4a4d8108
AM
14297+ err = deny_write_access(h_file);
14298+ if (unlikely(err)) {
14299+ fput(h_file);
14300+ h_file = ERR_PTR(err);
14301+ goto out_br;
14302+ }
14303+ }
953406b4 14304+ fsnotify_open(h_file);
4a4d8108 14305+ goto out; /* success */
1facf9fc 14306+
4f0767ce 14307+out_br:
acd2b654 14308+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 14309+out:
4a4d8108
AM
14310+ return h_file;
14311+}
1308ab2a 14312+
076b876e
AM
14313+static int au_cmoo(struct dentry *dentry)
14314+{
8b6a4947 14315+ int err, cmoo, matched;
076b876e
AM
14316+ unsigned int udba;
14317+ struct path h_path;
14318+ struct au_pin pin;
14319+ struct au_cp_generic cpg = {
14320+ .dentry = dentry,
14321+ .bdst = -1,
14322+ .bsrc = -1,
14323+ .len = -1,
14324+ .pin = &pin,
14325+ .flags = AuCpup_DTIME | AuCpup_HOPEN
14326+ };
7e9cd9fe 14327+ struct inode *delegated;
076b876e
AM
14328+ struct super_block *sb;
14329+ struct au_sbinfo *sbinfo;
14330+ struct au_fhsm *fhsm;
14331+ pid_t pid;
14332+ struct au_branch *br;
14333+ struct dentry *parent;
14334+ struct au_hinode *hdir;
14335+
14336+ DiMustWriteLock(dentry);
5527c038 14337+ IiMustWriteLock(d_inode(dentry));
076b876e
AM
14338+
14339+ err = 0;
14340+ if (IS_ROOT(dentry))
14341+ goto out;
5afbbe0d 14342+ cpg.bsrc = au_dbtop(dentry);
076b876e
AM
14343+ if (!cpg.bsrc)
14344+ goto out;
14345+
14346+ sb = dentry->d_sb;
14347+ sbinfo = au_sbi(sb);
14348+ fhsm = &sbinfo->si_fhsm;
14349+ pid = au_fhsm_pid(fhsm);
8b6a4947
AM
14350+ rcu_read_lock();
14351+ matched = (pid
14352+ && (current->pid == pid
14353+ || rcu_dereference(current->real_parent)->pid == pid));
14354+ rcu_read_unlock();
14355+ if (matched)
076b876e
AM
14356+ goto out;
14357+
14358+ br = au_sbr(sb, cpg.bsrc);
14359+ cmoo = au_br_cmoo(br->br_perm);
14360+ if (!cmoo)
14361+ goto out;
7e9cd9fe 14362+ if (!d_is_reg(dentry))
076b876e
AM
14363+ cmoo &= AuBrAttr_COO_ALL;
14364+ if (!cmoo)
14365+ goto out;
14366+
14367+ parent = dget_parent(dentry);
14368+ di_write_lock_parent(parent);
14369+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1);
14370+ cpg.bdst = err;
14371+ if (unlikely(err < 0)) {
14372+ err = 0; /* there is no upper writable branch */
14373+ goto out_dgrade;
14374+ }
14375+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst);
14376+
14377+ /* do not respect the coo attrib for the target branch */
14378+ err = au_cpup_dirs(dentry, cpg.bdst);
14379+ if (unlikely(err))
14380+ goto out_dgrade;
14381+
14382+ di_downgrade_lock(parent, AuLock_IR);
14383+ udba = au_opt_udba(sb);
14384+ err = au_pin(&pin, dentry, cpg.bdst, udba,
14385+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14386+ if (unlikely(err))
14387+ goto out_parent;
14388+
14389+ err = au_sio_cpup_simple(&cpg);
14390+ au_unpin(&pin);
14391+ if (unlikely(err))
14392+ goto out_parent;
14393+ if (!(cmoo & AuBrWAttr_MOO))
14394+ goto out_parent; /* success */
14395+
14396+ err = au_pin(&pin, dentry, cpg.bsrc, udba,
14397+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14398+ if (unlikely(err))
14399+ goto out_parent;
14400+
14401+ h_path.mnt = au_br_mnt(br);
14402+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc);
5527c038 14403+ hdir = au_hi(d_inode(parent), cpg.bsrc);
076b876e
AM
14404+ delegated = NULL;
14405+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1);
14406+ au_unpin(&pin);
14407+ /* todo: keep h_dentry or not? */
14408+ if (unlikely(err == -EWOULDBLOCK)) {
14409+ pr_warn("cannot retry for NFSv4 delegation"
14410+ " for an internal unlink\n");
14411+ iput(delegated);
14412+ }
14413+ if (unlikely(err)) {
14414+ pr_err("unlink %pd after coo failed (%d), ignored\n",
14415+ dentry, err);
14416+ err = 0;
14417+ }
14418+ goto out_parent; /* success */
14419+
14420+out_dgrade:
14421+ di_downgrade_lock(parent, AuLock_IR);
14422+out_parent:
14423+ di_read_unlock(parent, AuLock_IR);
14424+ dput(parent);
14425+out:
14426+ AuTraceErr(err);
14427+ return err;
14428+}
14429+
b912730e 14430+int au_do_open(struct file *file, struct au_do_open_args *args)
1facf9fc 14431+{
8b6a4947 14432+ int err, aopen = args->aopen;
1facf9fc 14433+ struct dentry *dentry;
076b876e 14434+ struct au_finfo *finfo;
1308ab2a 14435+
8b6a4947 14436+ if (!aopen)
b912730e
AM
14437+ err = au_finfo_init(file, args->fidir);
14438+ else {
14439+ lockdep_off();
14440+ err = au_finfo_init(file, args->fidir);
14441+ lockdep_on();
14442+ }
4a4d8108
AM
14443+ if (unlikely(err))
14444+ goto out;
1facf9fc 14445+
2000de60 14446+ dentry = file->f_path.dentry;
b912730e 14447+ AuDebugOn(IS_ERR_OR_NULL(dentry));
8b6a4947
AM
14448+ di_write_lock_child(dentry);
14449+ err = au_cmoo(dentry);
14450+ di_downgrade_lock(dentry, AuLock_IR);
14451+ if (!err) {
14452+ if (!aopen)
b912730e 14453+ err = args->open(file, vfsub_file_flags(file), NULL);
8b6a4947
AM
14454+ else {
14455+ lockdep_off();
acd2b654
AM
14456+ err = args->open(file, vfsub_file_flags(file),
14457+ args->h_file);
8b6a4947
AM
14458+ lockdep_on();
14459+ }
b912730e 14460+ }
8b6a4947 14461+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 14462+
076b876e
AM
14463+ finfo = au_fi(file);
14464+ if (!err) {
14465+ finfo->fi_file = file;
8b6a4947
AM
14466+ au_hbl_add(&finfo->fi_hlist,
14467+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
076b876e 14468+ }
8b6a4947 14469+ if (!aopen)
b912730e
AM
14470+ fi_write_unlock(file);
14471+ else {
14472+ lockdep_off();
14473+ fi_write_unlock(file);
14474+ lockdep_on();
14475+ }
4a4d8108 14476+ if (unlikely(err)) {
076b876e 14477+ finfo->fi_hdir = NULL;
1c60b727 14478+ au_finfo_fin(file);
1308ab2a 14479+ }
4a4d8108 14480+
4f0767ce 14481+out:
8b6a4947 14482+ AuTraceErr(err);
1308ab2a 14483+ return err;
14484+}
dece6358 14485+
4a4d8108 14486+int au_reopen_nondir(struct file *file)
1308ab2a 14487+{
4a4d8108 14488+ int err;
5afbbe0d 14489+ aufs_bindex_t btop;
4a4d8108 14490+ struct dentry *dentry;
acd2b654 14491+ struct au_branch *br;
4a4d8108 14492+ struct file *h_file, *h_file_tmp;
1308ab2a 14493+
2000de60 14494+ dentry = file->f_path.dentry;
5afbbe0d 14495+ btop = au_dbtop(dentry);
acd2b654 14496+ br = au_sbr(dentry->d_sb, btop);
4a4d8108 14497+ h_file_tmp = NULL;
5afbbe0d 14498+ if (au_fbtop(file) == btop) {
4a4d8108
AM
14499+ h_file = au_hf_top(file);
14500+ if (file->f_mode == h_file->f_mode)
14501+ return 0; /* success */
14502+ h_file_tmp = h_file;
14503+ get_file(h_file_tmp);
acd2b654 14504+ au_lcnt_inc(&br->br_nfiles);
5afbbe0d 14505+ au_set_h_fptr(file, btop, NULL);
4a4d8108
AM
14506+ }
14507+ AuDebugOn(au_fi(file)->fi_hdir);
86dc4139
AM
14508+ /*
14509+ * it can happen
14510+ * file exists on both of rw and ro
5afbbe0d 14511+ * open --> dbtop and fbtop are both 0
86dc4139
AM
14512+ * prepend a branch as rw, "rw" become ro
14513+ * remove rw/file
14514+ * delete the top branch, "rw" becomes rw again
5afbbe0d
AM
14515+ * --> dbtop is 1, fbtop is still 0
14516+ * write --> fbtop is 0 but dbtop is 1
86dc4139 14517+ */
5afbbe0d 14518+ /* AuDebugOn(au_fbtop(file) < btop); */
1308ab2a 14519+
5afbbe0d 14520+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC,
392086de 14521+ file, /*force_wr*/0);
4a4d8108 14522+ err = PTR_ERR(h_file);
86dc4139
AM
14523+ if (IS_ERR(h_file)) {
14524+ if (h_file_tmp) {
acd2b654 14525+ /* revert */
5afbbe0d 14526+ au_set_h_fptr(file, btop, h_file_tmp);
86dc4139
AM
14527+ h_file_tmp = NULL;
14528+ }
4a4d8108 14529+ goto out; /* todo: close all? */
86dc4139 14530+ }
4a4d8108
AM
14531+
14532+ err = 0;
5afbbe0d
AM
14533+ au_set_fbtop(file, btop);
14534+ au_set_h_fptr(file, btop, h_file);
4a4d8108
AM
14535+ au_update_figen(file);
14536+ /* todo: necessary? */
14537+ /* file->f_ra = h_file->f_ra; */
14538+
4f0767ce 14539+out:
acd2b654 14540+ if (h_file_tmp) {
4a4d8108 14541+ fput(h_file_tmp);
acd2b654
AM
14542+ au_lcnt_dec(&br->br_nfiles);
14543+ }
4a4d8108 14544+ return err;
1facf9fc 14545+}
14546+
1308ab2a 14547+/* ---------------------------------------------------------------------- */
14548+
4a4d8108
AM
14549+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
14550+ struct dentry *hi_wh)
1facf9fc 14551+{
4a4d8108 14552+ int err;
5afbbe0d 14553+ aufs_bindex_t btop;
4a4d8108
AM
14554+ struct au_dinfo *dinfo;
14555+ struct dentry *h_dentry;
14556+ struct au_hdentry *hdp;
1facf9fc 14557+
2000de60 14558+ dinfo = au_di(file->f_path.dentry);
4a4d8108 14559+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 14560+
5afbbe0d
AM
14561+ btop = dinfo->di_btop;
14562+ dinfo->di_btop = btgt;
14563+ hdp = au_hdentry(dinfo, btgt);
14564+ h_dentry = hdp->hd_dentry;
14565+ hdp->hd_dentry = hi_wh;
4a4d8108 14566+ err = au_reopen_nondir(file);
5afbbe0d
AM
14567+ hdp->hd_dentry = h_dentry;
14568+ dinfo->di_btop = btop;
1facf9fc 14569+
1facf9fc 14570+ return err;
14571+}
14572+
4a4d8108 14573+static int au_ready_to_write_wh(struct file *file, loff_t len,
86dc4139 14574+ aufs_bindex_t bcpup, struct au_pin *pin)
1facf9fc 14575+{
4a4d8108 14576+ int err;
027c5e7a 14577+ struct inode *inode, *h_inode;
c2b27bf2
AM
14578+ struct dentry *h_dentry, *hi_wh;
14579+ struct au_cp_generic cpg = {
2000de60 14580+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14581+ .bdst = bcpup,
14582+ .bsrc = -1,
14583+ .len = len,
14584+ .pin = pin
14585+ };
1facf9fc 14586+
5afbbe0d 14587+ au_update_dbtop(cpg.dentry);
5527c038 14588+ inode = d_inode(cpg.dentry);
027c5e7a 14589+ h_inode = NULL;
5afbbe0d
AM
14590+ if (au_dbtop(cpg.dentry) <= bcpup
14591+ && au_dbbot(cpg.dentry) >= bcpup) {
c2b27bf2 14592+ h_dentry = au_h_dptr(cpg.dentry, bcpup);
5527c038
JR
14593+ if (h_dentry && d_is_positive(h_dentry))
14594+ h_inode = d_inode(h_dentry);
027c5e7a 14595+ }
4a4d8108 14596+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 14597+ if (!hi_wh && !h_inode)
c2b27bf2 14598+ err = au_sio_cpup_wh(&cpg, file);
4a4d8108
AM
14599+ else
14600+ /* already copied-up after unlink */
14601+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 14602+
4a4d8108 14603+ if (!err
38d290e6
JR
14604+ && (inode->i_nlink > 1
14605+ || (inode->i_state & I_LINKABLE))
c2b27bf2
AM
14606+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK))
14607+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup));
1308ab2a 14608+
dece6358 14609+ return err;
1facf9fc 14610+}
14611+
4a4d8108
AM
14612+/*
14613+ * prepare the @file for writing.
14614+ */
14615+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 14616+{
4a4d8108 14617+ int err;
5afbbe0d 14618+ aufs_bindex_t dbtop;
c1595e42 14619+ struct dentry *parent;
86dc4139 14620+ struct inode *inode;
1facf9fc 14621+ struct super_block *sb;
4a4d8108 14622+ struct file *h_file;
c2b27bf2 14623+ struct au_cp_generic cpg = {
2000de60 14624+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14625+ .bdst = -1,
14626+ .bsrc = -1,
14627+ .len = len,
14628+ .pin = pin,
14629+ .flags = AuCpup_DTIME
14630+ };
1facf9fc 14631+
c2b27bf2 14632+ sb = cpg.dentry->d_sb;
5527c038 14633+ inode = d_inode(cpg.dentry);
5afbbe0d 14634+ cpg.bsrc = au_fbtop(file);
c2b27bf2 14635+ err = au_test_ro(sb, cpg.bsrc, inode);
4a4d8108 14636+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
c2b27bf2
AM
14637+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE,
14638+ /*flags*/0);
1facf9fc 14639+ goto out;
4a4d8108 14640+ }
1facf9fc 14641+
027c5e7a 14642+ /* need to cpup or reopen */
c2b27bf2 14643+ parent = dget_parent(cpg.dentry);
4a4d8108 14644+ di_write_lock_parent(parent);
c2b27bf2
AM
14645+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14646+ cpg.bdst = err;
4a4d8108
AM
14647+ if (unlikely(err < 0))
14648+ goto out_dgrade;
14649+ err = 0;
14650+
c2b27bf2
AM
14651+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) {
14652+ err = au_cpup_dirs(cpg.dentry, cpg.bdst);
1facf9fc 14653+ if (unlikely(err))
4a4d8108
AM
14654+ goto out_dgrade;
14655+ }
14656+
c2b27bf2 14657+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108
AM
14658+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14659+ if (unlikely(err))
14660+ goto out_dgrade;
14661+
5afbbe0d
AM
14662+ dbtop = au_dbtop(cpg.dentry);
14663+ if (dbtop <= cpg.bdst)
c2b27bf2 14664+ cpg.bsrc = cpg.bdst;
027c5e7a 14665+
5afbbe0d 14666+ if (dbtop <= cpg.bdst /* just reopen */
c2b27bf2 14667+ || !d_unhashed(cpg.dentry) /* copyup and reopen */
027c5e7a 14668+ ) {
392086de 14669+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0);
86dc4139 14670+ if (IS_ERR(h_file))
027c5e7a 14671+ err = PTR_ERR(h_file);
86dc4139 14672+ else {
027c5e7a 14673+ di_downgrade_lock(parent, AuLock_IR);
5afbbe0d 14674+ if (dbtop > cpg.bdst)
c2b27bf2 14675+ err = au_sio_cpup_simple(&cpg);
027c5e7a
AM
14676+ if (!err)
14677+ err = au_reopen_nondir(file);
c2b27bf2 14678+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file);
027c5e7a 14679+ }
027c5e7a
AM
14680+ } else { /* copyup as wh and reopen */
14681+ /*
14682+ * since writable hfsplus branch is not supported,
14683+ * h_open_pre/post() are unnecessary.
14684+ */
c2b27bf2 14685+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin);
4a4d8108 14686+ di_downgrade_lock(parent, AuLock_IR);
4a4d8108 14687+ }
4a4d8108
AM
14688+
14689+ if (!err) {
14690+ au_pin_set_parent_lflag(pin, /*lflag*/0);
14691+ goto out_dput; /* success */
14692+ }
14693+ au_unpin(pin);
14694+ goto out_unlock;
1facf9fc 14695+
4f0767ce 14696+out_dgrade:
4a4d8108 14697+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 14698+out_unlock:
4a4d8108 14699+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14700+out_dput:
4a4d8108 14701+ dput(parent);
4f0767ce 14702+out:
1facf9fc 14703+ return err;
14704+}
14705+
4a4d8108
AM
14706+/* ---------------------------------------------------------------------- */
14707+
14708+int au_do_flush(struct file *file, fl_owner_t id,
14709+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 14710+{
4a4d8108 14711+ int err;
1facf9fc 14712+ struct super_block *sb;
4a4d8108 14713+ struct inode *inode;
1facf9fc 14714+
c06a8ce3
AM
14715+ inode = file_inode(file);
14716+ sb = inode->i_sb;
4a4d8108
AM
14717+ si_noflush_read_lock(sb);
14718+ fi_read_lock(file);
b752ccd1 14719+ ii_read_lock_child(inode);
1facf9fc 14720+
4a4d8108
AM
14721+ err = flush(file, id);
14722+ au_cpup_attr_timesizes(inode);
1facf9fc 14723+
b752ccd1 14724+ ii_read_unlock(inode);
4a4d8108 14725+ fi_read_unlock(file);
1308ab2a 14726+ si_read_unlock(sb);
dece6358 14727+ return err;
1facf9fc 14728+}
14729+
4a4d8108
AM
14730+/* ---------------------------------------------------------------------- */
14731+
14732+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 14733+{
4a4d8108 14734+ int err;
4a4d8108
AM
14735+ struct au_pin pin;
14736+ struct au_finfo *finfo;
c2b27bf2 14737+ struct dentry *parent, *hi_wh;
4a4d8108 14738+ struct inode *inode;
1facf9fc 14739+ struct super_block *sb;
c2b27bf2 14740+ struct au_cp_generic cpg = {
2000de60 14741+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14742+ .bdst = -1,
14743+ .bsrc = -1,
14744+ .len = -1,
14745+ .pin = &pin,
14746+ .flags = AuCpup_DTIME
14747+ };
1facf9fc 14748+
4a4d8108
AM
14749+ FiMustWriteLock(file);
14750+
14751+ err = 0;
14752+ finfo = au_fi(file);
c2b27bf2 14753+ sb = cpg.dentry->d_sb;
5527c038 14754+ inode = d_inode(cpg.dentry);
5afbbe0d 14755+ cpg.bdst = au_ibtop(inode);
c2b27bf2 14756+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry))
1308ab2a 14757+ goto out;
dece6358 14758+
c2b27bf2
AM
14759+ parent = dget_parent(cpg.dentry);
14760+ if (au_test_ro(sb, cpg.bdst, inode)) {
4a4d8108 14761+ di_read_lock_parent(parent, !AuLock_IR);
c2b27bf2
AM
14762+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14763+ cpg.bdst = err;
4a4d8108
AM
14764+ di_read_unlock(parent, !AuLock_IR);
14765+ if (unlikely(err < 0))
14766+ goto out_parent;
14767+ err = 0;
1facf9fc 14768+ }
1facf9fc 14769+
4a4d8108 14770+ di_read_lock_parent(parent, AuLock_IR);
c2b27bf2 14771+ hi_wh = au_hi_wh(inode, cpg.bdst);
7f207e10
AM
14772+ if (!S_ISDIR(inode->i_mode)
14773+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108 14774+ && au_plink_test(inode)
c2b27bf2 14775+ && !d_unhashed(cpg.dentry)
5afbbe0d 14776+ && cpg.bdst < au_dbtop(cpg.dentry)) {
c2b27bf2 14777+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst);
4a4d8108
AM
14778+ if (unlikely(err))
14779+ goto out_unlock;
14780+
14781+ /* always superio. */
c2b27bf2 14782+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108 14783+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 14784+ if (!err) {
c2b27bf2 14785+ err = au_sio_cpup_simple(&cpg);
367653fa
AM
14786+ au_unpin(&pin);
14787+ }
4a4d8108
AM
14788+ } else if (hi_wh) {
14789+ /* already copied-up after unlink */
c2b27bf2 14790+ err = au_reopen_wh(file, cpg.bdst, hi_wh);
4a4d8108
AM
14791+ *need_reopen = 0;
14792+ }
1facf9fc 14793+
4f0767ce 14794+out_unlock:
4a4d8108 14795+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14796+out_parent:
4a4d8108 14797+ dput(parent);
4f0767ce 14798+out:
1308ab2a 14799+ return err;
dece6358 14800+}
1facf9fc 14801+
4a4d8108 14802+static void au_do_refresh_dir(struct file *file)
dece6358 14803+{
5afbbe0d 14804+ aufs_bindex_t bindex, bbot, new_bindex, brid;
4a4d8108
AM
14805+ struct au_hfile *p, tmp, *q;
14806+ struct au_finfo *finfo;
1308ab2a 14807+ struct super_block *sb;
4a4d8108 14808+ struct au_fidir *fidir;
1facf9fc 14809+
4a4d8108 14810+ FiMustWriteLock(file);
1facf9fc 14811+
2000de60 14812+ sb = file->f_path.dentry->d_sb;
4a4d8108
AM
14813+ finfo = au_fi(file);
14814+ fidir = finfo->fi_hdir;
14815+ AuDebugOn(!fidir);
14816+ p = fidir->fd_hfile + finfo->fi_btop;
14817+ brid = p->hf_br->br_id;
5afbbe0d
AM
14818+ bbot = fidir->fd_bbot;
14819+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) {
4a4d8108
AM
14820+ if (!p->hf_file)
14821+ continue;
1308ab2a 14822+
4a4d8108
AM
14823+ new_bindex = au_br_index(sb, p->hf_br->br_id);
14824+ if (new_bindex == bindex)
14825+ continue;
14826+ if (new_bindex < 0) {
14827+ au_set_h_fptr(file, bindex, NULL);
14828+ continue;
14829+ }
1308ab2a 14830+
4a4d8108
AM
14831+ /* swap two lower inode, and loop again */
14832+ q = fidir->fd_hfile + new_bindex;
14833+ tmp = *q;
14834+ *q = *p;
14835+ *p = tmp;
14836+ if (tmp.hf_file) {
14837+ bindex--;
14838+ p--;
14839+ }
14840+ }
1308ab2a 14841+
4a4d8108 14842+ p = fidir->fd_hfile;
2000de60 14843+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) {
5afbbe0d
AM
14844+ bbot = au_sbbot(sb);
14845+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot;
4a4d8108
AM
14846+ finfo->fi_btop++, p++)
14847+ if (p->hf_file) {
c06a8ce3 14848+ if (file_inode(p->hf_file))
4a4d8108 14849+ break;
1c60b727 14850+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14851+ }
14852+ } else {
5afbbe0d
AM
14853+ bbot = au_br_index(sb, brid);
14854+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot;
4a4d8108
AM
14855+ finfo->fi_btop++, p++)
14856+ if (p->hf_file)
1c60b727 14857+ au_hfput(p, /*execed*/0);
5afbbe0d 14858+ bbot = au_sbbot(sb);
4a4d8108 14859+ }
1308ab2a 14860+
5afbbe0d
AM
14861+ p = fidir->fd_hfile + bbot;
14862+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop;
4a4d8108
AM
14863+ fidir->fd_bbot--, p--)
14864+ if (p->hf_file) {
c06a8ce3 14865+ if (file_inode(p->hf_file))
4a4d8108 14866+ break;
1c60b727 14867+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14868+ }
14869+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 14870+}
14871+
4a4d8108
AM
14872+/*
14873+ * after branch manipulating, refresh the file.
14874+ */
14875+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 14876+{
e2f27e51 14877+ int err, need_reopen, nbr;
5afbbe0d 14878+ aufs_bindex_t bbot, bindex;
4a4d8108 14879+ struct dentry *dentry;
e2f27e51 14880+ struct super_block *sb;
1308ab2a 14881+ struct au_finfo *finfo;
4a4d8108 14882+ struct au_hfile *hfile;
1facf9fc 14883+
2000de60 14884+ dentry = file->f_path.dentry;
e2f27e51
AM
14885+ sb = dentry->d_sb;
14886+ nbr = au_sbbot(sb) + 1;
1308ab2a 14887+ finfo = au_fi(file);
4a4d8108
AM
14888+ if (!finfo->fi_hdir) {
14889+ hfile = &finfo->fi_htop;
14890+ AuDebugOn(!hfile->hf_file);
e2f27e51 14891+ bindex = au_br_index(sb, hfile->hf_br->br_id);
4a4d8108
AM
14892+ AuDebugOn(bindex < 0);
14893+ if (bindex != finfo->fi_btop)
5afbbe0d 14894+ au_set_fbtop(file, bindex);
4a4d8108 14895+ } else {
e2f27e51 14896+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0);
4a4d8108
AM
14897+ if (unlikely(err))
14898+ goto out;
14899+ au_do_refresh_dir(file);
14900+ }
1facf9fc 14901+
4a4d8108
AM
14902+ err = 0;
14903+ need_reopen = 1;
14904+ if (!au_test_mmapped(file))
14905+ err = au_file_refresh_by_inode(file, &need_reopen);
e2f27e51
AM
14906+ if (finfo->fi_hdir)
14907+ /* harmless if err */
14908+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1);
027c5e7a 14909+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
14910+ err = reopen(file);
14911+ if (!err) {
14912+ au_update_figen(file);
14913+ goto out; /* success */
14914+ }
14915+
14916+ /* error, close all lower files */
14917+ if (finfo->fi_hdir) {
5afbbe0d
AM
14918+ bbot = au_fbbot_dir(file);
14919+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++)
4a4d8108
AM
14920+ au_set_h_fptr(file, bindex, NULL);
14921+ }
1facf9fc 14922+
4f0767ce 14923+out:
1facf9fc 14924+ return err;
14925+}
14926+
4a4d8108
AM
14927+/* common function to regular file and dir */
14928+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 14929+ int wlock, unsigned int fi_lsc)
dece6358 14930+{
1308ab2a 14931+ int err;
4a4d8108 14932+ unsigned int sigen, figen;
5afbbe0d 14933+ aufs_bindex_t btop;
4a4d8108
AM
14934+ unsigned char pseudo_link;
14935+ struct dentry *dentry;
14936+ struct inode *inode;
1facf9fc 14937+
4a4d8108 14938+ err = 0;
2000de60 14939+ dentry = file->f_path.dentry;
5527c038 14940+ inode = d_inode(dentry);
4a4d8108 14941+ sigen = au_sigen(dentry->d_sb);
521ced18 14942+ fi_write_lock_nested(file, fi_lsc);
4a4d8108 14943+ figen = au_figen(file);
521ced18
JR
14944+ if (!fi_lsc)
14945+ di_write_lock_child(dentry);
14946+ else
14947+ di_write_lock_child2(dentry);
5afbbe0d
AM
14948+ btop = au_dbtop(dentry);
14949+ pseudo_link = (btop != au_ibtop(inode));
14950+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) {
4a4d8108
AM
14951+ if (!wlock) {
14952+ di_downgrade_lock(dentry, AuLock_IR);
14953+ fi_downgrade_lock(file);
14954+ }
14955+ goto out; /* success */
14956+ }
dece6358 14957+
4a4d8108 14958+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 14959+ if (au_digen_test(dentry, sigen)) {
4a4d8108 14960+ err = au_reval_dpath(dentry, sigen);
027c5e7a 14961+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 14962+ }
dece6358 14963+
027c5e7a
AM
14964+ if (!err)
14965+ err = refresh_file(file, reopen);
4a4d8108
AM
14966+ if (!err) {
14967+ if (!wlock) {
14968+ di_downgrade_lock(dentry, AuLock_IR);
14969+ fi_downgrade_lock(file);
14970+ }
14971+ } else {
14972+ di_write_unlock(dentry);
14973+ fi_write_unlock(file);
14974+ }
1facf9fc 14975+
4f0767ce 14976+out:
1308ab2a 14977+ return err;
14978+}
1facf9fc 14979+
4a4d8108
AM
14980+/* ---------------------------------------------------------------------- */
14981+
14982+/* cf. aufs_nopage() */
14983+/* for madvise(2) */
14984+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 14985+{
4a4d8108
AM
14986+ unlock_page(page);
14987+ return 0;
14988+}
1facf9fc 14989+
4a4d8108 14990+/* it will never be called, but necessary to support O_DIRECT */
5afbbe0d 14991+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
4a4d8108 14992+{ BUG(); return 0; }
1facf9fc 14993+
4a4d8108
AM
14994+/* they will never be called. */
14995+#ifdef CONFIG_AUFS_DEBUG
14996+static int aufs_write_begin(struct file *file, struct address_space *mapping,
14997+ loff_t pos, unsigned len, unsigned flags,
14998+ struct page **pagep, void **fsdata)
14999+{ AuUnsupport(); return 0; }
15000+static int aufs_write_end(struct file *file, struct address_space *mapping,
15001+ loff_t pos, unsigned len, unsigned copied,
15002+ struct page *page, void *fsdata)
15003+{ AuUnsupport(); return 0; }
15004+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
15005+{ AuUnsupport(); return 0; }
1308ab2a 15006+
4a4d8108
AM
15007+static int aufs_set_page_dirty(struct page *page)
15008+{ AuUnsupport(); return 0; }
392086de
AM
15009+static void aufs_invalidatepage(struct page *page, unsigned int offset,
15010+ unsigned int length)
4a4d8108
AM
15011+{ AuUnsupport(); }
15012+static int aufs_releasepage(struct page *page, gfp_t gfp)
15013+{ AuUnsupport(); return 0; }
79b8bda9 15014+#if 0 /* called by memory compaction regardless file */
4a4d8108 15015+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 15016+ struct page *page, enum migrate_mode mode)
4a4d8108 15017+{ AuUnsupport(); return 0; }
79b8bda9 15018+#endif
e2f27e51
AM
15019+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode)
15020+{ AuUnsupport(); return true; }
15021+static void aufs_putback_page(struct page *page)
15022+{ AuUnsupport(); }
4a4d8108
AM
15023+static int aufs_launder_page(struct page *page)
15024+{ AuUnsupport(); return 0; }
15025+static int aufs_is_partially_uptodate(struct page *page,
38d290e6
JR
15026+ unsigned long from,
15027+ unsigned long count)
4a4d8108 15028+{ AuUnsupport(); return 0; }
392086de
AM
15029+static void aufs_is_dirty_writeback(struct page *page, bool *dirty,
15030+ bool *writeback)
15031+{ AuUnsupport(); }
4a4d8108
AM
15032+static int aufs_error_remove_page(struct address_space *mapping,
15033+ struct page *page)
15034+{ AuUnsupport(); return 0; }
b4510431
AM
15035+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
15036+ sector_t *span)
15037+{ AuUnsupport(); return 0; }
15038+static void aufs_swap_deactivate(struct file *file)
15039+{ AuUnsupport(); }
4a4d8108
AM
15040+#endif /* CONFIG_AUFS_DEBUG */
15041+
15042+const struct address_space_operations aufs_aop = {
15043+ .readpage = aufs_readpage,
15044+ .direct_IO = aufs_direct_IO,
4a4d8108
AM
15045+#ifdef CONFIG_AUFS_DEBUG
15046+ .writepage = aufs_writepage,
4a4d8108
AM
15047+ /* no writepages, because of writepage */
15048+ .set_page_dirty = aufs_set_page_dirty,
15049+ /* no readpages, because of readpage */
15050+ .write_begin = aufs_write_begin,
15051+ .write_end = aufs_write_end,
15052+ /* no bmap, no block device */
15053+ .invalidatepage = aufs_invalidatepage,
15054+ .releasepage = aufs_releasepage,
79b8bda9
AM
15055+ /* is fallback_migrate_page ok? */
15056+ /* .migratepage = aufs_migratepage, */
e2f27e51
AM
15057+ .isolate_page = aufs_isolate_page,
15058+ .putback_page = aufs_putback_page,
4a4d8108
AM
15059+ .launder_page = aufs_launder_page,
15060+ .is_partially_uptodate = aufs_is_partially_uptodate,
392086de 15061+ .is_dirty_writeback = aufs_is_dirty_writeback,
b4510431
AM
15062+ .error_remove_page = aufs_error_remove_page,
15063+ .swap_activate = aufs_swap_activate,
15064+ .swap_deactivate = aufs_swap_deactivate
4a4d8108 15065+#endif /* CONFIG_AUFS_DEBUG */
dece6358 15066+};
7f207e10 15067diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
eca34b5c
AM
15068--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
15069+++ linux/fs/aufs/file.h 2019-07-11 15:42:14.465571210 +0200
9f237c51 15070@@ -0,0 +1,342 @@
062440b3 15071+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 15072+/*
ba1aed25 15073+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
15074+ *
15075+ * This program, aufs is free software; you can redistribute it and/or modify
15076+ * it under the terms of the GNU General Public License as published by
15077+ * the Free Software Foundation; either version 2 of the License, or
15078+ * (at your option) any later version.
15079+ *
15080+ * This program is distributed in the hope that it will be useful,
15081+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15082+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15083+ * GNU General Public License for more details.
15084+ *
15085+ * You should have received a copy of the GNU General Public License
523b37e3 15086+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 15087+ */
1facf9fc 15088+
4a4d8108
AM
15089+/*
15090+ * file operations
15091+ */
1facf9fc 15092+
4a4d8108
AM
15093+#ifndef __AUFS_FILE_H__
15094+#define __AUFS_FILE_H__
1facf9fc 15095+
4a4d8108 15096+#ifdef __KERNEL__
1facf9fc 15097+
2cbb1c4b 15098+#include <linux/file.h>
4a4d8108 15099+#include <linux/fs.h>
3c1bdaff 15100+#include <linux/mm_types.h>
4a4d8108 15101+#include <linux/poll.h>
4a4d8108 15102+#include "rwsem.h"
1facf9fc 15103+
4a4d8108
AM
15104+struct au_branch;
15105+struct au_hfile {
15106+ struct file *hf_file;
15107+ struct au_branch *hf_br;
15108+};
1facf9fc 15109+
4a4d8108
AM
15110+struct au_vdir;
15111+struct au_fidir {
15112+ aufs_bindex_t fd_bbot;
15113+ aufs_bindex_t fd_nent;
15114+ struct au_vdir *fd_vdir_cache;
15115+ struct au_hfile fd_hfile[];
15116+};
1facf9fc 15117+
4a4d8108 15118+static inline int au_fidir_sz(int nent)
dece6358 15119+{
4f0767ce
JR
15120+ AuDebugOn(nent < 0);
15121+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 15122+}
1facf9fc 15123+
4a4d8108
AM
15124+struct au_finfo {
15125+ atomic_t fi_generation;
dece6358 15126+
4a4d8108
AM
15127+ struct au_rwsem fi_rwsem;
15128+ aufs_bindex_t fi_btop;
15129+
15130+ /* do not union them */
15131+ struct { /* for non-dir */
15132+ struct au_hfile fi_htop;
2cbb1c4b 15133+ atomic_t fi_mmapped;
4a4d8108
AM
15134+ };
15135+ struct au_fidir *fi_hdir; /* for dir only */
523b37e3 15136+
8b6a4947 15137+ struct hlist_bl_node fi_hlist;
1c60b727 15138+ struct file *fi_file; /* very ugly */
9f237c51 15139+ struct rcu_head rcu;
4a4d8108 15140+} ____cacheline_aligned_in_smp;
1facf9fc 15141+
4a4d8108 15142+/* ---------------------------------------------------------------------- */
1facf9fc 15143+
4a4d8108
AM
15144+/* file.c */
15145+extern const struct address_space_operations aufs_aop;
15146+unsigned int au_file_roflags(unsigned int flags);
15147+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 15148+ struct file *file, int force_wr);
b912730e 15149+struct au_do_open_args {
8b6a4947 15150+ int aopen;
b912730e
AM
15151+ int (*open)(struct file *file, int flags,
15152+ struct file *h_file);
15153+ struct au_fidir *fidir;
15154+ struct file *h_file;
15155+};
15156+int au_do_open(struct file *file, struct au_do_open_args *args);
4a4d8108
AM
15157+int au_reopen_nondir(struct file *file);
15158+struct au_pin;
15159+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
15160+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 15161+ int wlock, unsigned int fi_lsc);
4a4d8108
AM
15162+int au_do_flush(struct file *file, fl_owner_t id,
15163+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 15164+
4a4d8108
AM
15165+/* poll.c */
15166+#ifdef CONFIG_AUFS_POLL
cd7a4cd9 15167+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt);
4a4d8108 15168+#endif
1facf9fc 15169+
4a4d8108
AM
15170+#ifdef CONFIG_AUFS_BR_HFSPLUS
15171+/* hfsplus.c */
392086de
AM
15172+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
15173+ int force_wr);
4a4d8108
AM
15174+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
15175+ struct file *h_file);
15176+#else
c1595e42
JR
15177+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
15178+ aufs_bindex_t bindex, int force_wr)
4a4d8108
AM
15179+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
15180+ struct file *h_file);
15181+#endif
1facf9fc 15182+
4a4d8108
AM
15183+/* f_op.c */
15184+extern const struct file_operations aufs_file_fop;
b912730e 15185+int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
4a4d8108 15186+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
521ced18 15187+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc);
4a4d8108 15188+
4a4d8108 15189+/* finfo.c */
f0c0a007 15190+void au_hfput(struct au_hfile *hf, int execed);
4a4d8108
AM
15191+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
15192+ struct file *h_file);
1facf9fc 15193+
4a4d8108 15194+void au_update_figen(struct file *file);
4a4d8108 15195+struct au_fidir *au_fidir_alloc(struct super_block *sb);
e2f27e51 15196+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
1facf9fc 15197+
4a4d8108 15198+void au_fi_init_once(void *_fi);
1c60b727 15199+void au_finfo_fin(struct file *file);
4a4d8108 15200+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 15201+
4a4d8108
AM
15202+/* ioctl.c */
15203+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
15204+#ifdef CONFIG_COMPAT
15205+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15206+ unsigned long arg);
c2b27bf2
AM
15207+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15208+ unsigned long arg);
b752ccd1 15209+#endif
1facf9fc 15210+
4a4d8108 15211+/* ---------------------------------------------------------------------- */
1facf9fc 15212+
4a4d8108
AM
15213+static inline struct au_finfo *au_fi(struct file *file)
15214+{
38d290e6 15215+ return file->private_data;
4a4d8108 15216+}
1facf9fc 15217+
4a4d8108 15218+/* ---------------------------------------------------------------------- */
1facf9fc 15219+
8b6a4947
AM
15220+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem)
15221+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem)
15222+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem)
15223+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem)
4a4d8108 15224+/*
8b6a4947
AM
15225+#define fi_read_trylock_nested(f) \
15226+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem)
15227+#define fi_write_trylock_nested(f) \
15228+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem)
15229+*/
15230+
15231+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem)
15232+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem)
15233+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem)
1308ab2a 15234+
521ced18
JR
15235+/* lock subclass for finfo */
15236+enum {
15237+ AuLsc_FI_1,
15238+ AuLsc_FI_2
15239+};
15240+
15241+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc)
15242+{
15243+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15244+}
15245+
15246+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc)
15247+{
15248+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15249+}
15250+
15251+/*
15252+ * fi_read_lock_1, fi_write_lock_1,
15253+ * fi_read_lock_2, fi_write_lock_2
15254+ */
15255+#define AuReadLockFunc(name) \
15256+static inline void fi_read_lock_##name(struct file *f) \
15257+{ fi_read_lock_nested(f, AuLsc_FI_##name); }
15258+
15259+#define AuWriteLockFunc(name) \
15260+static inline void fi_write_lock_##name(struct file *f) \
15261+{ fi_write_lock_nested(f, AuLsc_FI_##name); }
15262+
15263+#define AuRWLockFuncs(name) \
15264+ AuReadLockFunc(name) \
15265+ AuWriteLockFunc(name)
15266+
15267+AuRWLockFuncs(1);
15268+AuRWLockFuncs(2);
15269+
15270+#undef AuReadLockFunc
15271+#undef AuWriteLockFunc
15272+#undef AuRWLockFuncs
15273+
4a4d8108
AM
15274+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
15275+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
15276+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 15277+
1308ab2a 15278+/* ---------------------------------------------------------------------- */
15279+
4a4d8108 15280+/* todo: hard/soft set? */
5afbbe0d 15281+static inline aufs_bindex_t au_fbtop(struct file *file)
dece6358 15282+{
4a4d8108
AM
15283+ FiMustAnyLock(file);
15284+ return au_fi(file)->fi_btop;
15285+}
dece6358 15286+
5afbbe0d 15287+static inline aufs_bindex_t au_fbbot_dir(struct file *file)
4a4d8108
AM
15288+{
15289+ FiMustAnyLock(file);
15290+ AuDebugOn(!au_fi(file)->fi_hdir);
15291+ return au_fi(file)->fi_hdir->fd_bbot;
15292+}
1facf9fc 15293+
4a4d8108
AM
15294+static inline struct au_vdir *au_fvdir_cache(struct file *file)
15295+{
15296+ FiMustAnyLock(file);
15297+ AuDebugOn(!au_fi(file)->fi_hdir);
15298+ return au_fi(file)->fi_hdir->fd_vdir_cache;
15299+}
1facf9fc 15300+
5afbbe0d 15301+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15302+{
15303+ FiMustWriteLock(file);
15304+ au_fi(file)->fi_btop = bindex;
15305+}
1facf9fc 15306+
5afbbe0d 15307+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15308+{
15309+ FiMustWriteLock(file);
15310+ AuDebugOn(!au_fi(file)->fi_hdir);
15311+ au_fi(file)->fi_hdir->fd_bbot = bindex;
15312+}
1308ab2a 15313+
4a4d8108
AM
15314+static inline void au_set_fvdir_cache(struct file *file,
15315+ struct au_vdir *vdir_cache)
15316+{
15317+ FiMustWriteLock(file);
15318+ AuDebugOn(!au_fi(file)->fi_hdir);
15319+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
15320+}
dece6358 15321+
4a4d8108
AM
15322+static inline struct file *au_hf_top(struct file *file)
15323+{
15324+ FiMustAnyLock(file);
15325+ AuDebugOn(au_fi(file)->fi_hdir);
15326+ return au_fi(file)->fi_htop.hf_file;
15327+}
1facf9fc 15328+
4a4d8108
AM
15329+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
15330+{
15331+ FiMustAnyLock(file);
15332+ AuDebugOn(!au_fi(file)->fi_hdir);
15333+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
15334+}
15335+
4a4d8108
AM
15336+/* todo: memory barrier? */
15337+static inline unsigned int au_figen(struct file *f)
dece6358 15338+{
4a4d8108
AM
15339+ return atomic_read(&au_fi(f)->fi_generation);
15340+}
dece6358 15341+
2cbb1c4b
JR
15342+static inline void au_set_mmapped(struct file *f)
15343+{
15344+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
15345+ return;
0c3ec466 15346+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
15347+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
15348+ ;
15349+}
15350+
15351+static inline void au_unset_mmapped(struct file *f)
15352+{
15353+ atomic_dec(&au_fi(f)->fi_mmapped);
15354+}
15355+
4a4d8108
AM
15356+static inline int au_test_mmapped(struct file *f)
15357+{
2cbb1c4b
JR
15358+ return atomic_read(&au_fi(f)->fi_mmapped);
15359+}
15360+
15361+/* customize vma->vm_file */
15362+
15363+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
15364+ struct file *file)
15365+{
53392da6
AM
15366+ struct file *f;
15367+
15368+ f = vma->vm_file;
2cbb1c4b
JR
15369+ get_file(file);
15370+ vma->vm_file = file;
53392da6 15371+ fput(f);
2cbb1c4b
JR
15372+}
15373+
15374+#ifdef CONFIG_MMU
15375+#define AuDbgVmRegion(file, vma) do {} while (0)
15376+
15377+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15378+ struct file *file)
15379+{
15380+ au_do_vm_file_reset(vma, file);
15381+}
15382+#else
15383+#define AuDbgVmRegion(file, vma) \
15384+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
15385+
15386+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15387+ struct file *file)
15388+{
53392da6
AM
15389+ struct file *f;
15390+
2cbb1c4b 15391+ au_do_vm_file_reset(vma, file);
53392da6 15392+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
15393+ get_file(file);
15394+ vma->vm_region->vm_file = file;
53392da6 15395+ fput(f);
2cbb1c4b
JR
15396+}
15397+#endif /* CONFIG_MMU */
15398+
15399+/* handle vma->vm_prfile */
fb47a38f 15400+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
2cbb1c4b
JR
15401+ struct file *file)
15402+{
2cbb1c4b
JR
15403+ get_file(file);
15404+ vma->vm_prfile = file;
15405+#ifndef CONFIG_MMU
15406+ get_file(file);
15407+ vma->vm_region->vm_prfile = file;
15408+#endif
fb47a38f 15409+}
1308ab2a 15410+
4a4d8108
AM
15411+#endif /* __KERNEL__ */
15412+#endif /* __AUFS_FILE_H__ */
7f207e10 15413diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
eca34b5c
AM
15414--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
15415+++ linux/fs/aufs/finfo.c 2019-07-11 15:42:14.465571210 +0200
062440b3 15416@@ -0,0 +1,149 @@
cd7a4cd9 15417+// SPDX-License-Identifier: GPL-2.0
4a4d8108 15418+/*
ba1aed25 15419+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
15420+ *
15421+ * This program, aufs is free software; you can redistribute it and/or modify
15422+ * it under the terms of the GNU General Public License as published by
15423+ * the Free Software Foundation; either version 2 of the License, or
15424+ * (at your option) any later version.
15425+ *
15426+ * This program is distributed in the hope that it will be useful,
15427+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15428+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15429+ * GNU General Public License for more details.
15430+ *
15431+ * You should have received a copy of the GNU General Public License
523b37e3 15432+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 15433+ */
1308ab2a 15434+
4a4d8108
AM
15435+/*
15436+ * file private data
15437+ */
1facf9fc 15438+
4a4d8108 15439+#include "aufs.h"
1facf9fc 15440+
f0c0a007 15441+void au_hfput(struct au_hfile *hf, int execed)
4a4d8108 15442+{
f0c0a007 15443+ if (execed)
4a4d8108
AM
15444+ allow_write_access(hf->hf_file);
15445+ fput(hf->hf_file);
15446+ hf->hf_file = NULL;
acd2b654 15447+ au_lcnt_dec(&hf->hf_br->br_nfiles);
4a4d8108
AM
15448+ hf->hf_br = NULL;
15449+}
1facf9fc 15450+
4a4d8108
AM
15451+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
15452+{
15453+ struct au_finfo *finfo = au_fi(file);
15454+ struct au_hfile *hf;
15455+ struct au_fidir *fidir;
15456+
15457+ fidir = finfo->fi_hdir;
15458+ if (!fidir) {
15459+ AuDebugOn(finfo->fi_btop != bindex);
15460+ hf = &finfo->fi_htop;
15461+ } else
15462+ hf = fidir->fd_hfile + bindex;
15463+
15464+ if (hf && hf->hf_file)
f0c0a007 15465+ au_hfput(hf, vfsub_file_execed(file));
4a4d8108
AM
15466+ if (val) {
15467+ FiMustWriteLock(file);
b912730e 15468+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry));
4a4d8108 15469+ hf->hf_file = val;
2000de60 15470+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex);
1308ab2a 15471+ }
4a4d8108 15472+}
1facf9fc 15473+
4a4d8108
AM
15474+void au_update_figen(struct file *file)
15475+{
2000de60 15476+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry));
4a4d8108 15477+ /* smp_mb(); */ /* atomic_set */
1facf9fc 15478+}
15479+
4a4d8108
AM
15480+/* ---------------------------------------------------------------------- */
15481+
4a4d8108
AM
15482+struct au_fidir *au_fidir_alloc(struct super_block *sb)
15483+{
15484+ struct au_fidir *fidir;
15485+ int nbr;
15486+
5afbbe0d 15487+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
15488+ if (nbr < 2)
15489+ nbr = 2; /* initial allocate for 2 branches */
15490+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
15491+ if (fidir) {
15492+ fidir->fd_bbot = -1;
15493+ fidir->fd_nent = nbr;
4a4d8108
AM
15494+ }
15495+
15496+ return fidir;
15497+}
15498+
e2f27e51 15499+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink)
4a4d8108
AM
15500+{
15501+ int err;
15502+ struct au_fidir *fidir, *p;
15503+
15504+ AuRwMustWriteLock(&finfo->fi_rwsem);
15505+ fidir = finfo->fi_hdir;
15506+ AuDebugOn(!fidir);
15507+
15508+ err = -ENOMEM;
15509+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
e2f27e51 15510+ GFP_NOFS, may_shrink);
4a4d8108
AM
15511+ if (p) {
15512+ p->fd_nent = nbr;
15513+ finfo->fi_hdir = p;
15514+ err = 0;
15515+ }
1facf9fc 15516+
dece6358 15517+ return err;
1facf9fc 15518+}
1308ab2a 15519+
15520+/* ---------------------------------------------------------------------- */
15521+
1c60b727 15522+void au_finfo_fin(struct file *file)
1308ab2a 15523+{
4a4d8108
AM
15524+ struct au_finfo *finfo;
15525+
acd2b654 15526+ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles);
7f207e10 15527+
4a4d8108
AM
15528+ finfo = au_fi(file);
15529+ AuDebugOn(finfo->fi_hdir);
15530+ AuRwDestroy(&finfo->fi_rwsem);
1c60b727 15531+ au_cache_free_finfo(finfo);
1308ab2a 15532+}
1308ab2a 15533+
e49829fe 15534+void au_fi_init_once(void *_finfo)
4a4d8108 15535+{
e49829fe 15536+ struct au_finfo *finfo = _finfo;
1308ab2a 15537+
e49829fe 15538+ au_rw_init(&finfo->fi_rwsem);
4a4d8108 15539+}
1308ab2a 15540+
4a4d8108
AM
15541+int au_finfo_init(struct file *file, struct au_fidir *fidir)
15542+{
1716fcea 15543+ int err;
4a4d8108
AM
15544+ struct au_finfo *finfo;
15545+ struct dentry *dentry;
15546+
15547+ err = -ENOMEM;
2000de60 15548+ dentry = file->f_path.dentry;
4a4d8108
AM
15549+ finfo = au_cache_alloc_finfo();
15550+ if (unlikely(!finfo))
15551+ goto out;
15552+
15553+ err = 0;
acd2b654 15554+ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles);
4a4d8108
AM
15555+ au_rw_write_lock(&finfo->fi_rwsem);
15556+ finfo->fi_btop = -1;
15557+ finfo->fi_hdir = fidir;
15558+ atomic_set(&finfo->fi_generation, au_digen(dentry));
15559+ /* smp_mb(); */ /* atomic_set */
15560+
15561+ file->private_data = finfo;
15562+
15563+out:
15564+ return err;
15565+}
7f207e10 15566diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
eca34b5c
AM
15567--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
15568+++ linux/fs/aufs/f_op.c 2019-07-11 15:42:14.465571210 +0200
acd2b654 15569@@ -0,0 +1,819 @@
cd7a4cd9 15570+// SPDX-License-Identifier: GPL-2.0
dece6358 15571+/*
ba1aed25 15572+ * Copyright (C) 2005-2019 Junjiro R. Okajima
dece6358
AM
15573+ *
15574+ * This program, aufs is free software; you can redistribute it and/or modify
15575+ * it under the terms of the GNU General Public License as published by
15576+ * the Free Software Foundation; either version 2 of the License, or
15577+ * (at your option) any later version.
15578+ *
15579+ * This program is distributed in the hope that it will be useful,
15580+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15581+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15582+ * GNU General Public License for more details.
15583+ *
15584+ * You should have received a copy of the GNU General Public License
523b37e3 15585+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 15586+ */
1facf9fc 15587+
15588+/*
4a4d8108 15589+ * file and vm operations
1facf9fc 15590+ */
dece6358 15591+
86dc4139 15592+#include <linux/aio.h>
4a4d8108
AM
15593+#include <linux/fs_stack.h>
15594+#include <linux/mman.h>
4a4d8108 15595+#include <linux/security.h>
dece6358
AM
15596+#include "aufs.h"
15597+
b912730e 15598+int au_do_open_nondir(struct file *file, int flags, struct file *h_file)
1facf9fc 15599+{
4a4d8108
AM
15600+ int err;
15601+ aufs_bindex_t bindex;
8cdd5066 15602+ struct dentry *dentry, *h_dentry;
4a4d8108 15603+ struct au_finfo *finfo;
38d290e6 15604+ struct inode *h_inode;
4a4d8108
AM
15605+
15606+ FiMustWriteLock(file);
15607+
523b37e3 15608+ err = 0;
2000de60 15609+ dentry = file->f_path.dentry;
b912730e 15610+ AuDebugOn(IS_ERR_OR_NULL(dentry));
4a4d8108
AM
15611+ finfo = au_fi(file);
15612+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 15613+ atomic_set(&finfo->fi_mmapped, 0);
5afbbe0d 15614+ bindex = au_dbtop(dentry);
8cdd5066
JR
15615+ if (!h_file) {
15616+ h_dentry = au_h_dptr(dentry, bindex);
15617+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15618+ if (unlikely(err))
15619+ goto out;
b912730e 15620+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
acd2b654
AM
15621+ if (IS_ERR(h_file)) {
15622+ err = PTR_ERR(h_file);
15623+ goto out;
15624+ }
8cdd5066
JR
15625+ } else {
15626+ h_dentry = h_file->f_path.dentry;
15627+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15628+ if (unlikely(err))
15629+ goto out;
acd2b654 15630+ /* br ref is already inc-ed */
8cdd5066 15631+ }
acd2b654
AM
15632+
15633+ if ((flags & __O_TMPFILE)
15634+ && !(flags & O_EXCL)) {
15635+ h_inode = file_inode(h_file);
15636+ spin_lock(&h_inode->i_lock);
15637+ h_inode->i_state |= I_LINKABLE;
15638+ spin_unlock(&h_inode->i_lock);
4a4d8108 15639+ }
acd2b654
AM
15640+ au_set_fbtop(file, bindex);
15641+ au_set_h_fptr(file, bindex, h_file);
15642+ au_update_figen(file);
15643+ /* todo: necessary? */
15644+ /* file->f_ra = h_file->f_ra; */
027c5e7a 15645+
8cdd5066 15646+out:
4a4d8108 15647+ return err;
1facf9fc 15648+}
15649+
4a4d8108
AM
15650+static int aufs_open_nondir(struct inode *inode __maybe_unused,
15651+ struct file *file)
1facf9fc 15652+{
4a4d8108 15653+ int err;
1308ab2a 15654+ struct super_block *sb;
b912730e
AM
15655+ struct au_do_open_args args = {
15656+ .open = au_do_open_nondir
15657+ };
1facf9fc 15658+
523b37e3
AM
15659+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n",
15660+ file, vfsub_file_flags(file), file->f_mode);
1facf9fc 15661+
2000de60 15662+ sb = file->f_path.dentry->d_sb;
4a4d8108 15663+ si_read_lock(sb, AuLock_FLUSH);
b912730e 15664+ err = au_do_open(file, &args);
4a4d8108
AM
15665+ si_read_unlock(sb);
15666+ return err;
15667+}
1facf9fc 15668+
4a4d8108
AM
15669+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
15670+{
15671+ struct au_finfo *finfo;
15672+ aufs_bindex_t bindex;
1facf9fc 15673+
4a4d8108 15674+ finfo = au_fi(file);
8b6a4947
AM
15675+ au_hbl_del(&finfo->fi_hlist,
15676+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108 15677+ bindex = finfo->fi_btop;
b4510431 15678+ if (bindex >= 0)
4a4d8108 15679+ au_set_h_fptr(file, bindex, NULL);
7f207e10 15680+
1c60b727 15681+ au_finfo_fin(file);
4a4d8108 15682+ return 0;
1facf9fc 15683+}
15684+
4a4d8108
AM
15685+/* ---------------------------------------------------------------------- */
15686+
15687+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 15688+{
1308ab2a 15689+ int err;
4a4d8108
AM
15690+ struct file *h_file;
15691+
15692+ err = 0;
15693+ h_file = au_hf_top(file);
15694+ if (h_file)
15695+ err = vfsub_flush(h_file, id);
15696+ return err;
15697+}
15698+
15699+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
15700+{
15701+ return au_do_flush(file, id, au_do_flush_nondir);
15702+}
15703+
15704+/* ---------------------------------------------------------------------- */
9dbd164d
AM
15705+/*
15706+ * read and write functions acquire [fdi]_rwsem once, but release before
15707+ * mmap_sem. This is because to stop a race condition between mmap(2).
acd2b654 15708+ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping
9dbd164d
AM
15709+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
15710+ * read functions after [fdi]_rwsem are released, but it should be harmless.
15711+ */
4a4d8108 15712+
b912730e 15713+/* Callers should call au_read_post() or fput() in the end */
521ced18 15714+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc)
4a4d8108 15715+{
4a4d8108 15716+ struct file *h_file;
b912730e 15717+ int err;
1facf9fc 15718+
521ced18 15719+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc);
b912730e
AM
15720+ if (!err) {
15721+ di_read_unlock(file->f_path.dentry, AuLock_IR);
15722+ h_file = au_hf_top(file);
15723+ get_file(h_file);
15724+ if (!keep_fi)
15725+ fi_read_unlock(file);
15726+ } else
15727+ h_file = ERR_PTR(err);
15728+
15729+ return h_file;
15730+}
15731+
15732+static void au_read_post(struct inode *inode, struct file *h_file)
15733+{
15734+ /* update without lock, I don't think it a problem */
15735+ fsstack_copy_attr_atime(inode, file_inode(h_file));
15736+ fput(h_file);
15737+}
15738+
15739+struct au_write_pre {
521ced18
JR
15740+ /* input */
15741+ unsigned int lsc;
15742+
15743+ /* output */
b912730e 15744+ blkcnt_t blks;
5afbbe0d 15745+ aufs_bindex_t btop;
b912730e
AM
15746+};
15747+
15748+/*
15749+ * return with iinfo is write-locked
15750+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the
15751+ * end
15752+ */
15753+static struct file *au_write_pre(struct file *file, int do_ready,
15754+ struct au_write_pre *wpre)
15755+{
15756+ struct file *h_file;
15757+ struct dentry *dentry;
15758+ int err;
521ced18 15759+ unsigned int lsc;
b912730e
AM
15760+ struct au_pin pin;
15761+
521ced18
JR
15762+ lsc = 0;
15763+ if (wpre)
15764+ lsc = wpre->lsc;
15765+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc);
b912730e 15766+ h_file = ERR_PTR(err);
dece6358
AM
15767+ if (unlikely(err))
15768+ goto out;
1facf9fc 15769+
b912730e
AM
15770+ dentry = file->f_path.dentry;
15771+ if (do_ready) {
15772+ err = au_ready_to_write(file, -1, &pin);
15773+ if (unlikely(err)) {
15774+ h_file = ERR_PTR(err);
15775+ di_write_unlock(dentry);
15776+ goto out_fi;
15777+ }
15778+ }
15779+
15780+ di_downgrade_lock(dentry, /*flags*/0);
15781+ if (wpre)
5afbbe0d 15782+ wpre->btop = au_fbtop(file);
4a4d8108 15783+ h_file = au_hf_top(file);
9dbd164d 15784+ get_file(h_file);
b912730e
AM
15785+ if (wpre)
15786+ wpre->blks = file_inode(h_file)->i_blocks;
15787+ if (do_ready)
15788+ au_unpin(&pin);
15789+ di_read_unlock(dentry, /*flags*/0);
15790+
15791+out_fi:
15792+ fi_write_unlock(file);
15793+out:
15794+ return h_file;
15795+}
15796+
15797+static void au_write_post(struct inode *inode, struct file *h_file,
15798+ struct au_write_pre *wpre, ssize_t written)
15799+{
15800+ struct inode *h_inode;
15801+
15802+ au_cpup_attr_timesizes(inode);
5afbbe0d 15803+ AuDebugOn(au_ibtop(inode) != wpre->btop);
b912730e
AM
15804+ h_inode = file_inode(h_file);
15805+ inode->i_mode = h_inode->i_mode;
15806+ ii_write_unlock(inode);
b912730e
AM
15807+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */
15808+ if (written > 0)
5afbbe0d 15809+ au_fhsm_wrote(inode->i_sb, wpre->btop,
b912730e 15810+ /*force*/h_inode->i_blocks > wpre->blks);
1c60b727 15811+ fput(h_file);
b912730e
AM
15812+}
15813+
15814+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
15815+ loff_t *ppos)
15816+{
15817+ ssize_t err;
15818+ struct inode *inode;
15819+ struct file *h_file;
15820+ struct super_block *sb;
15821+
15822+ inode = file_inode(file);
15823+ sb = inode->i_sb;
15824+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
15825+
521ced18 15826+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
15827+ err = PTR_ERR(h_file);
15828+ if (IS_ERR(h_file))
15829+ goto out;
9dbd164d
AM
15830+
15831+ /* filedata may be obsoleted by concurrent copyup, but no problem */
4a4d8108
AM
15832+ err = vfsub_read_u(h_file, buf, count, ppos);
15833+ /* todo: necessary? */
15834+ /* file->f_ra = h_file->f_ra; */
b912730e 15835+ au_read_post(inode, h_file);
1308ab2a 15836+
4f0767ce 15837+out:
dece6358
AM
15838+ si_read_unlock(sb);
15839+ return err;
15840+}
1facf9fc 15841+
e49829fe
JR
15842+/*
15843+ * todo: very ugly
15844+ * it locks both of i_mutex and si_rwsem for read in safe.
15845+ * if the plink maintenance mode continues forever (that is the problem),
15846+ * may loop forever.
15847+ */
15848+static void au_mtx_and_read_lock(struct inode *inode)
15849+{
15850+ int err;
15851+ struct super_block *sb = inode->i_sb;
15852+
15853+ while (1) {
febd17d6 15854+ inode_lock(inode);
e49829fe
JR
15855+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15856+ if (!err)
15857+ break;
febd17d6 15858+ inode_unlock(inode);
e49829fe
JR
15859+ si_read_lock(sb, AuLock_NOPLMW);
15860+ si_read_unlock(sb);
15861+ }
15862+}
15863+
4a4d8108
AM
15864+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
15865+ size_t count, loff_t *ppos)
dece6358 15866+{
4a4d8108 15867+ ssize_t err;
b912730e
AM
15868+ struct au_write_pre wpre;
15869+ struct inode *inode;
4a4d8108
AM
15870+ struct file *h_file;
15871+ char __user *buf = (char __user *)ubuf;
1facf9fc 15872+
b912730e 15873+ inode = file_inode(file);
e49829fe 15874+ au_mtx_and_read_lock(inode);
1facf9fc 15875+
521ced18 15876+ wpre.lsc = 0;
b912730e
AM
15877+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15878+ err = PTR_ERR(h_file);
15879+ if (IS_ERR(h_file))
9dbd164d 15880+ goto out;
9dbd164d 15881+
4a4d8108 15882+ err = vfsub_write_u(h_file, buf, count, ppos);
b912730e 15883+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15884+
4f0767ce 15885+out:
b912730e 15886+ si_read_unlock(inode->i_sb);
febd17d6 15887+ inode_unlock(inode);
dece6358
AM
15888+ return err;
15889+}
1facf9fc 15890+
076b876e
AM
15891+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio,
15892+ struct iov_iter *iov_iter)
dece6358 15893+{
4a4d8108
AM
15894+ ssize_t err;
15895+ struct file *file;
076b876e 15896+ ssize_t (*iter)(struct kiocb *, struct iov_iter *);
1facf9fc 15897+
4a4d8108
AM
15898+ err = security_file_permission(h_file, rw);
15899+ if (unlikely(err))
15900+ goto out;
1facf9fc 15901+
4a4d8108 15902+ err = -ENOSYS;
076b876e 15903+ iter = NULL;
5527c038 15904+ if (rw == MAY_READ)
076b876e 15905+ iter = h_file->f_op->read_iter;
5527c038 15906+ else if (rw == MAY_WRITE)
076b876e 15907+ iter = h_file->f_op->write_iter;
076b876e
AM
15908+
15909+ file = kio->ki_filp;
15910+ kio->ki_filp = h_file;
15911+ if (iter) {
2cbb1c4b 15912+ lockdep_off();
076b876e
AM
15913+ err = iter(kio, iov_iter);
15914+ lockdep_on();
4a4d8108
AM
15915+ } else
15916+ /* currently there is no such fs */
15917+ WARN_ON_ONCE(1);
076b876e 15918+ kio->ki_filp = file;
1facf9fc 15919+
4f0767ce 15920+out:
dece6358
AM
15921+ return err;
15922+}
1facf9fc 15923+
076b876e 15924+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1facf9fc 15925+{
4a4d8108
AM
15926+ ssize_t err;
15927+ struct file *file, *h_file;
b912730e 15928+ struct inode *inode;
dece6358 15929+ struct super_block *sb;
1facf9fc 15930+
4a4d8108 15931+ file = kio->ki_filp;
b912730e
AM
15932+ inode = file_inode(file);
15933+ sb = inode->i_sb;
e49829fe 15934+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 15935+
521ced18 15936+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0);
b912730e
AM
15937+ err = PTR_ERR(h_file);
15938+ if (IS_ERR(h_file))
15939+ goto out;
9dbd164d 15940+
5afbbe0d
AM
15941+ if (au_test_loopback_kthread()) {
15942+ au_warn_loopback(h_file->f_path.dentry->d_sb);
15943+ if (file->f_mapping != h_file->f_mapping) {
15944+ file->f_mapping = h_file->f_mapping;
15945+ smp_mb(); /* unnecessary? */
15946+ }
15947+ }
15948+ fi_read_unlock(file);
15949+
076b876e 15950+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter);
4a4d8108
AM
15951+ /* todo: necessary? */
15952+ /* file->f_ra = h_file->f_ra; */
b912730e 15953+ au_read_post(inode, h_file);
1facf9fc 15954+
4f0767ce 15955+out:
4a4d8108 15956+ si_read_unlock(sb);
1308ab2a 15957+ return err;
15958+}
1facf9fc 15959+
076b876e 15960+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1308ab2a 15961+{
4a4d8108 15962+ ssize_t err;
b912730e
AM
15963+ struct au_write_pre wpre;
15964+ struct inode *inode;
4a4d8108 15965+ struct file *file, *h_file;
1308ab2a 15966+
4a4d8108 15967+ file = kio->ki_filp;
b912730e 15968+ inode = file_inode(file);
e49829fe
JR
15969+ au_mtx_and_read_lock(inode);
15970+
521ced18 15971+ wpre.lsc = 0;
b912730e
AM
15972+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15973+ err = PTR_ERR(h_file);
15974+ if (IS_ERR(h_file))
9dbd164d 15975+ goto out;
9dbd164d 15976+
076b876e 15977+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter);
b912730e 15978+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15979+
4f0767ce 15980+out:
b912730e 15981+ si_read_unlock(inode->i_sb);
febd17d6 15982+ inode_unlock(inode);
dece6358 15983+ return err;
1facf9fc 15984+}
15985+
4a4d8108
AM
15986+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
15987+ struct pipe_inode_info *pipe, size_t len,
15988+ unsigned int flags)
1facf9fc 15989+{
4a4d8108
AM
15990+ ssize_t err;
15991+ struct file *h_file;
b912730e 15992+ struct inode *inode;
dece6358 15993+ struct super_block *sb;
1facf9fc 15994+
b912730e
AM
15995+ inode = file_inode(file);
15996+ sb = inode->i_sb;
e49829fe 15997+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 15998+
521ced18 15999+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
16000+ err = PTR_ERR(h_file);
16001+ if (IS_ERR(h_file))
dece6358 16002+ goto out;
1facf9fc 16003+
4a4d8108 16004+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
acd2b654 16005+ /* todo: necessary? */
4a4d8108 16006+ /* file->f_ra = h_file->f_ra; */
b912730e 16007+ au_read_post(inode, h_file);
1facf9fc 16008+
4f0767ce 16009+out:
4a4d8108 16010+ si_read_unlock(sb);
dece6358 16011+ return err;
1facf9fc 16012+}
16013+
4a4d8108
AM
16014+static ssize_t
16015+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
16016+ size_t len, unsigned int flags)
1facf9fc 16017+{
4a4d8108 16018+ ssize_t err;
b912730e
AM
16019+ struct au_write_pre wpre;
16020+ struct inode *inode;
076b876e 16021+ struct file *h_file;
1facf9fc 16022+
b912730e 16023+ inode = file_inode(file);
e49829fe 16024+ au_mtx_and_read_lock(inode);
9dbd164d 16025+
521ced18 16026+ wpre.lsc = 0;
b912730e
AM
16027+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16028+ err = PTR_ERR(h_file);
16029+ if (IS_ERR(h_file))
9dbd164d 16030+ goto out;
9dbd164d 16031+
4a4d8108 16032+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
b912730e 16033+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 16034+
4f0767ce 16035+out:
b912730e 16036+ si_read_unlock(inode->i_sb);
febd17d6 16037+ inode_unlock(inode);
4a4d8108
AM
16038+ return err;
16039+}
1facf9fc 16040+
38d290e6
JR
16041+static long aufs_fallocate(struct file *file, int mode, loff_t offset,
16042+ loff_t len)
16043+{
16044+ long err;
b912730e 16045+ struct au_write_pre wpre;
38d290e6
JR
16046+ struct inode *inode;
16047+ struct file *h_file;
16048+
b912730e 16049+ inode = file_inode(file);
38d290e6
JR
16050+ au_mtx_and_read_lock(inode);
16051+
521ced18 16052+ wpre.lsc = 0;
b912730e
AM
16053+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16054+ err = PTR_ERR(h_file);
16055+ if (IS_ERR(h_file))
38d290e6 16056+ goto out;
38d290e6
JR
16057+
16058+ lockdep_off();
03673fb0 16059+ err = vfs_fallocate(h_file, mode, offset, len);
38d290e6 16060+ lockdep_on();
b912730e 16061+ au_write_post(inode, h_file, &wpre, /*written*/1);
38d290e6
JR
16062+
16063+out:
b912730e 16064+ si_read_unlock(inode->i_sb);
febd17d6 16065+ inode_unlock(inode);
38d290e6
JR
16066+ return err;
16067+}
16068+
521ced18
JR
16069+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos,
16070+ struct file *dst, loff_t dst_pos,
16071+ size_t len, unsigned int flags)
16072+{
16073+ ssize_t err;
16074+ struct au_write_pre wpre;
16075+ enum { SRC, DST };
16076+ struct {
16077+ struct inode *inode;
16078+ struct file *h_file;
16079+ struct super_block *h_sb;
16080+ } a[2];
16081+#define a_src a[SRC]
16082+#define a_dst a[DST]
16083+
16084+ err = -EINVAL;
16085+ a_src.inode = file_inode(src);
16086+ if (unlikely(!S_ISREG(a_src.inode->i_mode)))
16087+ goto out;
16088+ a_dst.inode = file_inode(dst);
16089+ if (unlikely(!S_ISREG(a_dst.inode->i_mode)))
16090+ goto out;
16091+
16092+ au_mtx_and_read_lock(a_dst.inode);
16093+ /*
16094+ * in order to match the order in di_write_lock2_{child,parent}(),
acd2b654 16095+ * use f_path.dentry for this comparison.
521ced18
JR
16096+ */
16097+ if (src->f_path.dentry < dst->f_path.dentry) {
16098+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1);
16099+ err = PTR_ERR(a_src.h_file);
16100+ if (IS_ERR(a_src.h_file))
16101+ goto out_si;
16102+
16103+ wpre.lsc = AuLsc_FI_2;
16104+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
16105+ err = PTR_ERR(a_dst.h_file);
16106+ if (IS_ERR(a_dst.h_file)) {
16107+ au_read_post(a_src.inode, a_src.h_file);
16108+ goto out_si;
16109+ }
16110+ } else {
16111+ wpre.lsc = AuLsc_FI_1;
16112+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
16113+ err = PTR_ERR(a_dst.h_file);
16114+ if (IS_ERR(a_dst.h_file))
16115+ goto out_si;
16116+
16117+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2);
16118+ err = PTR_ERR(a_src.h_file);
16119+ if (IS_ERR(a_src.h_file)) {
16120+ au_write_post(a_dst.inode, a_dst.h_file, &wpre,
16121+ /*written*/0);
16122+ goto out_si;
16123+ }
16124+ }
16125+
16126+ err = -EXDEV;
16127+ a_src.h_sb = file_inode(a_src.h_file)->i_sb;
16128+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb;
16129+ if (unlikely(a_src.h_sb != a_dst.h_sb)) {
16130+ AuDbgFile(src);
16131+ AuDbgFile(dst);
16132+ goto out_file;
16133+ }
16134+
16135+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file,
16136+ dst_pos, len, flags);
16137+
16138+out_file:
16139+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err);
16140+ fi_read_unlock(src);
16141+ au_read_post(a_src.inode, a_src.h_file);
16142+out_si:
16143+ si_read_unlock(a_dst.inode->i_sb);
16144+ inode_unlock(a_dst.inode);
16145+out:
16146+ return err;
16147+#undef a_src
16148+#undef a_dst
16149+}
16150+
4a4d8108
AM
16151+/* ---------------------------------------------------------------------- */
16152+
9dbd164d
AM
16153+/*
16154+ * The locking order around current->mmap_sem.
16155+ * - in most and regular cases
16156+ * file I/O syscall -- aufs_read() or something
16157+ * -- si_rwsem for read -- mmap_sem
16158+ * (Note that [fdi]i_rwsem are released before mmap_sem).
16159+ * - in mmap case
16160+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
acd2b654
AM
16161+ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for
16162+ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held
16163+ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
9dbd164d
AM
16164+ * It means that when aufs acquires si_rwsem for write, the process should never
16165+ * acquire mmap_sem.
16166+ *
392086de 16167+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a
9dbd164d
AM
16168+ * problem either since any directory is not able to be mmap-ed.
16169+ * The similar scenario is applied to aufs_readlink() too.
16170+ */
16171+
38d290e6 16172+#if 0 /* stop calling security_file_mmap() */
2dfbb274
AM
16173+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
16174+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
16175+
16176+static unsigned long au_arch_prot_conv(unsigned long flags)
16177+{
16178+ /* currently ppc64 only */
16179+#ifdef CONFIG_PPC64
16180+ /* cf. linux/arch/powerpc/include/asm/mman.h */
16181+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
16182+ return AuConv_VM_PROT(flags, SAO);
16183+#else
16184+ AuDebugOn(arch_calc_vm_prot_bits(-1));
16185+ return 0;
16186+#endif
16187+}
16188+
16189+static unsigned long au_prot_conv(unsigned long flags)
16190+{
16191+ return AuConv_VM_PROT(flags, READ)
16192+ | AuConv_VM_PROT(flags, WRITE)
16193+ | AuConv_VM_PROT(flags, EXEC)
16194+ | au_arch_prot_conv(flags);
16195+}
16196+
16197+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
16198+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
16199+
16200+static unsigned long au_flag_conv(unsigned long flags)
16201+{
16202+ return AuConv_VM_MAP(flags, GROWSDOWN)
16203+ | AuConv_VM_MAP(flags, DENYWRITE)
2dfbb274
AM
16204+ | AuConv_VM_MAP(flags, LOCKED);
16205+}
38d290e6 16206+#endif
2dfbb274 16207+
9dbd164d 16208+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 16209+{
4a4d8108 16210+ int err;
4a4d8108 16211+ const unsigned char wlock
9dbd164d 16212+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108 16213+ struct super_block *sb;
9dbd164d 16214+ struct file *h_file;
b912730e 16215+ struct inode *inode;
9dbd164d
AM
16216+
16217+ AuDbgVmRegion(file, vma);
1308ab2a 16218+
b912730e
AM
16219+ inode = file_inode(file);
16220+ sb = inode->i_sb;
9dbd164d 16221+ lockdep_off();
e49829fe 16222+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108 16223+
b912730e 16224+ h_file = au_write_pre(file, wlock, /*wpre*/NULL);
9dbd164d 16225+ lockdep_on();
b912730e
AM
16226+ err = PTR_ERR(h_file);
16227+ if (IS_ERR(h_file))
16228+ goto out;
1308ab2a 16229+
b912730e
AM
16230+ err = 0;
16231+ au_set_mmapped(file);
9dbd164d 16232+ au_vm_file_reset(vma, h_file);
38d290e6
JR
16233+ /*
16234+ * we cannot call security_mmap_file() here since it may acquire
16235+ * mmap_sem or i_mutex.
16236+ *
16237+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags),
16238+ * au_flag_conv(vma->vm_flags));
16239+ */
9dbd164d 16240+ if (!err)
521ced18 16241+ err = call_mmap(h_file, vma);
b912730e
AM
16242+ if (!err) {
16243+ au_vm_prfile_set(vma, file);
16244+ fsstack_copy_attr_atime(inode, file_inode(h_file));
16245+ goto out_fput; /* success */
16246+ }
2cbb1c4b
JR
16247+ au_unset_mmapped(file);
16248+ au_vm_file_reset(vma, file);
b912730e 16249+
2cbb1c4b 16250+out_fput:
9dbd164d 16251+ lockdep_off();
b912730e
AM
16252+ ii_write_unlock(inode);
16253+ lockdep_on();
16254+ fput(h_file);
4f0767ce 16255+out:
b912730e 16256+ lockdep_off();
9dbd164d
AM
16257+ si_read_unlock(sb);
16258+ lockdep_on();
16259+ AuTraceErr(err);
4a4d8108
AM
16260+ return err;
16261+}
16262+
16263+/* ---------------------------------------------------------------------- */
16264+
1e00d052
AM
16265+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
16266+ int datasync)
4a4d8108
AM
16267+{
16268+ int err;
b912730e 16269+ struct au_write_pre wpre;
4a4d8108
AM
16270+ struct inode *inode;
16271+ struct file *h_file;
4a4d8108
AM
16272+
16273+ err = 0; /* -EBADF; */ /* posix? */
16274+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
b912730e 16275+ goto out;
4a4d8108 16276+
b912730e
AM
16277+ inode = file_inode(file);
16278+ au_mtx_and_read_lock(inode);
16279+
521ced18 16280+ wpre.lsc = 0;
b912730e
AM
16281+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16282+ err = PTR_ERR(h_file);
16283+ if (IS_ERR(h_file))
4a4d8108 16284+ goto out_unlock;
4a4d8108 16285+
53392da6 16286+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
b912730e 16287+ au_write_post(inode, h_file, &wpre, /*written*/0);
4a4d8108 16288+
4f0767ce 16289+out_unlock:
b912730e 16290+ si_read_unlock(inode->i_sb);
febd17d6 16291+ inode_unlock(inode);
b912730e 16292+out:
4a4d8108 16293+ return err;
dece6358
AM
16294+}
16295+
4a4d8108 16296+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 16297+{
4a4d8108
AM
16298+ int err;
16299+ struct file *h_file;
4a4d8108 16300+ struct super_block *sb;
1308ab2a 16301+
b912730e 16302+ sb = file->f_path.dentry->d_sb;
e49829fe 16303+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 16304+
521ced18 16305+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
16306+ err = PTR_ERR(h_file);
16307+ if (IS_ERR(h_file))
4a4d8108
AM
16308+ goto out;
16309+
523b37e3 16310+ if (h_file->f_op->fasync)
4a4d8108 16311+ err = h_file->f_op->fasync(fd, h_file, flag);
b912730e 16312+ fput(h_file); /* instead of au_read_post() */
1308ab2a 16313+
4f0767ce 16314+out:
4a4d8108 16315+ si_read_unlock(sb);
1308ab2a 16316+ return err;
dece6358 16317+}
4a4d8108 16318+
febd17d6
JR
16319+static int aufs_setfl(struct file *file, unsigned long arg)
16320+{
16321+ int err;
16322+ struct file *h_file;
16323+ struct super_block *sb;
16324+
16325+ sb = file->f_path.dentry->d_sb;
16326+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
16327+
521ced18 16328+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
febd17d6
JR
16329+ err = PTR_ERR(h_file);
16330+ if (IS_ERR(h_file))
16331+ goto out;
16332+
1c60b727
AM
16333+ /* stop calling h_file->fasync */
16334+ arg |= vfsub_file_flags(file) & FASYNC;
febd17d6
JR
16335+ err = setfl(/*unused fd*/-1, h_file, arg);
16336+ fput(h_file); /* instead of au_read_post() */
16337+
16338+out:
16339+ si_read_unlock(sb);
16340+ return err;
16341+}
16342+
4a4d8108
AM
16343+/* ---------------------------------------------------------------------- */
16344+
16345+/* no one supports this operation, currently */
16346+#if 0
16347+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
2000de60 16348+ size_t len, loff_t *pos, int more)
4a4d8108
AM
16349+{
16350+}
16351+#endif
16352+
16353+/* ---------------------------------------------------------------------- */
16354+
16355+const struct file_operations aufs_file_fop = {
16356+ .owner = THIS_MODULE,
2cbb1c4b 16357+
027c5e7a 16358+ .llseek = default_llseek,
4a4d8108
AM
16359+
16360+ .read = aufs_read,
16361+ .write = aufs_write,
076b876e
AM
16362+ .read_iter = aufs_read_iter,
16363+ .write_iter = aufs_write_iter,
16364+
4a4d8108
AM
16365+#ifdef CONFIG_AUFS_POLL
16366+ .poll = aufs_poll,
16367+#endif
16368+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1 16369+#ifdef CONFIG_COMPAT
c2b27bf2 16370+ .compat_ioctl = aufs_compat_ioctl_nondir,
b752ccd1 16371+#endif
4a4d8108
AM
16372+ .mmap = aufs_mmap,
16373+ .open = aufs_open_nondir,
16374+ .flush = aufs_flush_nondir,
16375+ .release = aufs_release_nondir,
16376+ .fsync = aufs_fsync_nondir,
4a4d8108
AM
16377+ .fasync = aufs_fasync,
16378+ /* .sendpage = aufs_sendpage, */
febd17d6 16379+ .setfl = aufs_setfl,
4a4d8108
AM
16380+ .splice_write = aufs_splice_write,
16381+ .splice_read = aufs_splice_read,
16382+#if 0
16383+ .aio_splice_write = aufs_aio_splice_write,
38d290e6 16384+ .aio_splice_read = aufs_aio_splice_read,
4a4d8108 16385+#endif
521ced18
JR
16386+ .fallocate = aufs_fallocate,
16387+ .copy_file_range = aufs_copy_file_range
4a4d8108 16388+};
7f207e10 16389diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
eca34b5c
AM
16390--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
16391+++ linux/fs/aufs/fstype.h 2019-07-11 15:42:14.465571210 +0200
062440b3
AM
16392@@ -0,0 +1,401 @@
16393+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 16394+/*
ba1aed25 16395+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
16396+ *
16397+ * This program, aufs is free software; you can redistribute it and/or modify
16398+ * it under the terms of the GNU General Public License as published by
16399+ * the Free Software Foundation; either version 2 of the License, or
16400+ * (at your option) any later version.
16401+ *
16402+ * This program is distributed in the hope that it will be useful,
16403+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16404+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16405+ * GNU General Public License for more details.
16406+ *
16407+ * You should have received a copy of the GNU General Public License
523b37e3 16408+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
16409+ */
16410+
16411+/*
16412+ * judging filesystem type
16413+ */
16414+
16415+#ifndef __AUFS_FSTYPE_H__
16416+#define __AUFS_FSTYPE_H__
16417+
16418+#ifdef __KERNEL__
16419+
16420+#include <linux/fs.h>
16421+#include <linux/magic.h>
b912730e 16422+#include <linux/nfs_fs.h>
b95c5147 16423+#include <linux/romfs_fs.h>
4a4d8108
AM
16424+
16425+static inline int au_test_aufs(struct super_block *sb)
16426+{
16427+ return sb->s_magic == AUFS_SUPER_MAGIC;
16428+}
16429+
16430+static inline const char *au_sbtype(struct super_block *sb)
16431+{
16432+ return sb->s_type->name;
16433+}
1308ab2a 16434+
16435+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
16436+{
f0c0a007 16437+#if IS_ENABLED(CONFIG_ISO9660_FS)
2000de60 16438+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
16439+#else
16440+ return 0;
16441+#endif
16442+}
16443+
1308ab2a 16444+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 16445+{
f0c0a007 16446+#if IS_ENABLED(CONFIG_ROMFS_FS)
2000de60 16447+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
16448+#else
16449+ return 0;
16450+#endif
16451+}
16452+
1308ab2a 16453+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 16454+{
f0c0a007 16455+#if IS_ENABLED(CONFIG_CRAMFS)
1308ab2a 16456+ return sb->s_magic == CRAMFS_MAGIC;
16457+#endif
16458+ return 0;
16459+}
16460+
16461+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
16462+{
f0c0a007 16463+#if IS_ENABLED(CONFIG_NFS_FS)
1308ab2a 16464+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
16465+#else
16466+ return 0;
16467+#endif
16468+}
16469+
1308ab2a 16470+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 16471+{
f0c0a007 16472+#if IS_ENABLED(CONFIG_FUSE_FS)
1308ab2a 16473+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
16474+#else
16475+ return 0;
16476+#endif
16477+}
16478+
1308ab2a 16479+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 16480+{
f0c0a007 16481+#if IS_ENABLED(CONFIG_XFS_FS)
1308ab2a 16482+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
16483+#else
16484+ return 0;
16485+#endif
16486+}
16487+
1308ab2a 16488+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 16489+{
1308ab2a 16490+#ifdef CONFIG_TMPFS
16491+ return sb->s_magic == TMPFS_MAGIC;
16492+#else
16493+ return 0;
dece6358 16494+#endif
dece6358
AM
16495+}
16496+
1308ab2a 16497+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 16498+{
f0c0a007 16499+#if IS_ENABLED(CONFIG_ECRYPT_FS)
1308ab2a 16500+ return !strcmp(au_sbtype(sb), "ecryptfs");
16501+#else
16502+ return 0;
16503+#endif
1facf9fc 16504+}
16505+
1308ab2a 16506+static inline int au_test_ramfs(struct super_block *sb)
16507+{
16508+ return sb->s_magic == RAMFS_MAGIC;
16509+}
16510+
16511+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
16512+{
f0c0a007 16513+#if IS_ENABLED(CONFIG_UBIFS_FS)
1308ab2a 16514+ return sb->s_magic == UBIFS_SUPER_MAGIC;
16515+#else
16516+ return 0;
16517+#endif
16518+}
16519+
16520+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
16521+{
16522+#ifdef CONFIG_PROC_FS
16523+ return sb->s_magic == PROC_SUPER_MAGIC;
16524+#else
16525+ return 0;
16526+#endif
16527+}
16528+
16529+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
16530+{
16531+#ifdef CONFIG_SYSFS
16532+ return sb->s_magic == SYSFS_MAGIC;
16533+#else
16534+ return 0;
16535+#endif
16536+}
16537+
16538+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
16539+{
f0c0a007 16540+#if IS_ENABLED(CONFIG_CONFIGFS_FS)
1308ab2a 16541+ return sb->s_magic == CONFIGFS_MAGIC;
16542+#else
16543+ return 0;
16544+#endif
16545+}
16546+
16547+static inline int au_test_minix(struct super_block *sb __maybe_unused)
16548+{
f0c0a007 16549+#if IS_ENABLED(CONFIG_MINIX_FS)
1308ab2a 16550+ return sb->s_magic == MINIX3_SUPER_MAGIC
16551+ || sb->s_magic == MINIX2_SUPER_MAGIC
16552+ || sb->s_magic == MINIX2_SUPER_MAGIC2
16553+ || sb->s_magic == MINIX_SUPER_MAGIC
16554+ || sb->s_magic == MINIX_SUPER_MAGIC2;
16555+#else
16556+ return 0;
16557+#endif
16558+}
16559+
1308ab2a 16560+static inline int au_test_fat(struct super_block *sb __maybe_unused)
16561+{
f0c0a007 16562+#if IS_ENABLED(CONFIG_FAT_FS)
1308ab2a 16563+ return sb->s_magic == MSDOS_SUPER_MAGIC;
16564+#else
16565+ return 0;
16566+#endif
16567+}
16568+
16569+static inline int au_test_msdos(struct super_block *sb)
16570+{
16571+ return au_test_fat(sb);
16572+}
16573+
16574+static inline int au_test_vfat(struct super_block *sb)
16575+{
16576+ return au_test_fat(sb);
16577+}
16578+
16579+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
16580+{
16581+#ifdef CONFIG_SECURITYFS
16582+ return sb->s_magic == SECURITYFS_MAGIC;
16583+#else
16584+ return 0;
16585+#endif
16586+}
16587+
16588+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
16589+{
f0c0a007 16590+#if IS_ENABLED(CONFIG_SQUASHFS)
1308ab2a 16591+ return sb->s_magic == SQUASHFS_MAGIC;
16592+#else
16593+ return 0;
16594+#endif
16595+}
16596+
16597+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
16598+{
f0c0a007 16599+#if IS_ENABLED(CONFIG_BTRFS_FS)
1308ab2a 16600+ return sb->s_magic == BTRFS_SUPER_MAGIC;
16601+#else
16602+ return 0;
16603+#endif
16604+}
16605+
16606+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
16607+{
f0c0a007 16608+#if IS_ENABLED(CONFIG_XENFS)
1308ab2a 16609+ return sb->s_magic == XENFS_SUPER_MAGIC;
16610+#else
16611+ return 0;
16612+#endif
16613+}
16614+
16615+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
16616+{
16617+#ifdef CONFIG_DEBUG_FS
16618+ return sb->s_magic == DEBUGFS_MAGIC;
16619+#else
16620+ return 0;
16621+#endif
16622+}
16623+
16624+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
16625+{
f0c0a007 16626+#if IS_ENABLED(CONFIG_NILFS)
1308ab2a 16627+ return sb->s_magic == NILFS_SUPER_MAGIC;
16628+#else
16629+ return 0;
16630+#endif
16631+}
16632+
4a4d8108
AM
16633+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
16634+{
f0c0a007 16635+#if IS_ENABLED(CONFIG_HFSPLUS_FS)
4a4d8108
AM
16636+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
16637+#else
16638+ return 0;
16639+#endif
16640+}
16641+
1308ab2a 16642+/* ---------------------------------------------------------------------- */
16643+/*
16644+ * they can't be an aufs branch.
16645+ */
16646+static inline int au_test_fs_unsuppoted(struct super_block *sb)
16647+{
16648+ return
16649+#ifndef CONFIG_AUFS_BR_RAMFS
16650+ au_test_ramfs(sb) ||
16651+#endif
16652+ au_test_procfs(sb)
16653+ || au_test_sysfs(sb)
16654+ || au_test_configfs(sb)
16655+ || au_test_debugfs(sb)
16656+ || au_test_securityfs(sb)
16657+ || au_test_xenfs(sb)
16658+ || au_test_ecryptfs(sb)
16659+ /* || !strcmp(au_sbtype(sb), "unionfs") */
16660+ || au_test_aufs(sb); /* will be supported in next version */
16661+}
16662+
1308ab2a 16663+static inline int au_test_fs_remote(struct super_block *sb)
16664+{
16665+ return !au_test_tmpfs(sb)
16666+#ifdef CONFIG_AUFS_BR_RAMFS
16667+ && !au_test_ramfs(sb)
16668+#endif
16669+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
16670+}
16671+
16672+/* ---------------------------------------------------------------------- */
16673+
16674+/*
16675+ * Note: these functions (below) are created after reading ->getattr() in all
16676+ * filesystems under linux/fs. it means we have to do so in every update...
16677+ */
16678+
16679+/*
16680+ * some filesystems require getattr to refresh the inode attributes before
16681+ * referencing.
16682+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
16683+ * and leave the work for d_revalidate()
16684+ */
16685+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
16686+{
16687+ return au_test_nfs(sb)
16688+ || au_test_fuse(sb)
1308ab2a 16689+ /* || au_test_btrfs(sb) */ /* untested */
1308ab2a 16690+ ;
16691+}
16692+
16693+/*
16694+ * filesystems which don't maintain i_size or i_blocks.
16695+ */
16696+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
16697+{
16698+ return au_test_xfs(sb)
4a4d8108
AM
16699+ || au_test_btrfs(sb)
16700+ || au_test_ubifs(sb)
16701+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 16702+ /* || au_test_minix(sb) */ /* untested */
16703+ ;
16704+}
16705+
16706+/*
16707+ * filesystems which don't store the correct value in some of their inode
16708+ * attributes.
16709+ */
16710+static inline int au_test_fs_bad_iattr(struct super_block *sb)
16711+{
16712+ return au_test_fs_bad_iattr_size(sb)
1308ab2a 16713+ || au_test_fat(sb)
16714+ || au_test_msdos(sb)
16715+ || au_test_vfat(sb);
1facf9fc 16716+}
16717+
16718+/* they don't check i_nlink in link(2) */
16719+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
16720+{
16721+ return au_test_tmpfs(sb)
16722+#ifdef CONFIG_AUFS_BR_RAMFS
16723+ || au_test_ramfs(sb)
16724+#endif
4a4d8108 16725+ || au_test_ubifs(sb)
4a4d8108 16726+ || au_test_hfsplus(sb);
1facf9fc 16727+}
16728+
16729+/*
16730+ * filesystems which sets S_NOATIME and S_NOCMTIME.
16731+ */
16732+static inline int au_test_fs_notime(struct super_block *sb)
16733+{
16734+ return au_test_nfs(sb)
16735+ || au_test_fuse(sb)
dece6358 16736+ || au_test_ubifs(sb)
1facf9fc 16737+ ;
16738+}
16739+
1facf9fc 16740+/* temporary support for i#1 in cramfs */
16741+static inline int au_test_fs_unique_ino(struct inode *inode)
16742+{
16743+ if (au_test_cramfs(inode->i_sb))
16744+ return inode->i_ino != 1;
16745+ return 1;
16746+}
16747+
16748+/* ---------------------------------------------------------------------- */
16749+
16750+/*
16751+ * the filesystem where the xino files placed must support i/o after unlink and
16752+ * maintain i_size and i_blocks.
16753+ */
16754+static inline int au_test_fs_bad_xino(struct super_block *sb)
16755+{
16756+ return au_test_fs_remote(sb)
16757+ || au_test_fs_bad_iattr_size(sb)
1facf9fc 16758+ /* don't want unnecessary work for xino */
16759+ || au_test_aufs(sb)
1308ab2a 16760+ || au_test_ecryptfs(sb)
16761+ || au_test_nilfs(sb);
1facf9fc 16762+}
16763+
16764+static inline int au_test_fs_trunc_xino(struct super_block *sb)
16765+{
16766+ return au_test_tmpfs(sb)
16767+ || au_test_ramfs(sb);
16768+}
16769+
16770+/*
16771+ * test if the @sb is real-readonly.
16772+ */
16773+static inline int au_test_fs_rr(struct super_block *sb)
16774+{
16775+ return au_test_squashfs(sb)
16776+ || au_test_iso9660(sb)
16777+ || au_test_cramfs(sb)
16778+ || au_test_romfs(sb);
16779+}
16780+
b912730e
AM
16781+/*
16782+ * test if the @inode is nfs with 'noacl' option
2121bcd9 16783+ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e
AM
16784+ */
16785+static inline int au_test_nfs_noacl(struct inode *inode)
16786+{
16787+ return au_test_nfs(inode->i_sb)
16788+ /* && IS_POSIXACL(inode) */
16789+ && !nfs_server_capable(inode, NFS_CAP_ACLS);
16790+}
16791+
1facf9fc 16792+#endif /* __KERNEL__ */
16793+#endif /* __AUFS_FSTYPE_H__ */
8b6a4947 16794diff -urN /usr/share/empty/fs/aufs/hbl.h linux/fs/aufs/hbl.h
eca34b5c
AM
16795--- /usr/share/empty/fs/aufs/hbl.h 1970-01-01 01:00:00.000000000 +0100
16796+++ linux/fs/aufs/hbl.h 2019-07-11 15:42:14.465571210 +0200
062440b3
AM
16797@@ -0,0 +1,65 @@
16798+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 16799+/*
ba1aed25 16800+ * Copyright (C) 2017-2019 Junjiro R. Okajima
8b6a4947
AM
16801+ *
16802+ * This program, aufs is free software; you can redistribute it and/or modify
16803+ * it under the terms of the GNU General Public License as published by
16804+ * the Free Software Foundation; either version 2 of the License, or
16805+ * (at your option) any later version.
16806+ *
16807+ * This program is distributed in the hope that it will be useful,
16808+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16809+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16810+ * GNU General Public License for more details.
16811+ *
16812+ * You should have received a copy of the GNU General Public License
16813+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16814+ */
16815+
16816+/*
16817+ * helpers for hlist_bl.h
16818+ */
16819+
16820+#ifndef __AUFS_HBL_H__
16821+#define __AUFS_HBL_H__
16822+
16823+#ifdef __KERNEL__
16824+
16825+#include <linux/list_bl.h>
16826+
16827+static inline void au_hbl_add(struct hlist_bl_node *node,
16828+ struct hlist_bl_head *hbl)
16829+{
16830+ hlist_bl_lock(hbl);
16831+ hlist_bl_add_head(node, hbl);
16832+ hlist_bl_unlock(hbl);
16833+}
16834+
16835+static inline void au_hbl_del(struct hlist_bl_node *node,
16836+ struct hlist_bl_head *hbl)
16837+{
16838+ hlist_bl_lock(hbl);
16839+ hlist_bl_del(node);
16840+ hlist_bl_unlock(hbl);
16841+}
16842+
16843+#define au_hbl_for_each(pos, head) \
16844+ for (pos = hlist_bl_first(head); \
16845+ pos; \
16846+ pos = pos->next)
16847+
16848+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl)
16849+{
16850+ unsigned long cnt;
16851+ struct hlist_bl_node *pos;
16852+
16853+ cnt = 0;
16854+ hlist_bl_lock(hbl);
16855+ au_hbl_for_each(pos, hbl)
16856+ cnt++;
16857+ hlist_bl_unlock(hbl);
16858+ return cnt;
16859+}
16860+
16861+#endif /* __KERNEL__ */
16862+#endif /* __AUFS_HBL_H__ */
7f207e10 16863diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
eca34b5c
AM
16864--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
16865+++ linux/fs/aufs/hfsnotify.c 2019-07-11 15:42:14.465571210 +0200
fbc438ed 16866@@ -0,0 +1,288 @@
cd7a4cd9 16867+// SPDX-License-Identifier: GPL-2.0
1facf9fc 16868+/*
ba1aed25 16869+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 16870+ *
16871+ * This program, aufs is free software; you can redistribute it and/or modify
16872+ * it under the terms of the GNU General Public License as published by
16873+ * the Free Software Foundation; either version 2 of the License, or
16874+ * (at your option) any later version.
dece6358
AM
16875+ *
16876+ * This program is distributed in the hope that it will be useful,
16877+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16878+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16879+ * GNU General Public License for more details.
16880+ *
16881+ * You should have received a copy of the GNU General Public License
523b37e3 16882+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 16883+ */
16884+
16885+/*
4a4d8108 16886+ * fsnotify for the lower directories
1facf9fc 16887+ */
16888+
16889+#include "aufs.h"
16890+
4a4d8108
AM
16891+/* FS_IN_IGNORED is unnecessary */
16892+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
16893+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 16894+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 16895+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 16896+
0c5527e5 16897+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 16898+{
0c5527e5
AM
16899+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
16900+ hn_mark);
5afbbe0d 16901+ /* AuDbg("here\n"); */
1c60b727 16902+ au_cache_free_hnotify(hn);
8b6a4947 16903+ smp_mb__before_atomic(); /* for atomic64_dec */
1716fcea
AM
16904+ if (atomic64_dec_and_test(&au_hfsn_ifree))
16905+ wake_up(&au_hfsn_wq);
4a4d8108 16906+}
1facf9fc 16907+
027c5e7a 16908+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 16909+{
1716fcea 16910+ int err;
027c5e7a
AM
16911+ struct au_hnotify *hn;
16912+ struct super_block *sb;
16913+ struct au_branch *br;
0c5527e5 16914+ struct fsnotify_mark *mark;
027c5e7a 16915+ aufs_bindex_t bindex;
1facf9fc 16916+
027c5e7a
AM
16917+ hn = hinode->hi_notify;
16918+ sb = hn->hn_aufs_inode->i_sb;
16919+ bindex = au_br_index(sb, hinode->hi_id);
16920+ br = au_sbr(sb, bindex);
1716fcea
AM
16921+ AuDebugOn(!br->br_hfsn);
16922+
0c5527e5 16923+ mark = &hn->hn_mark;
ffa93bbd 16924+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group);
0c5527e5 16925+ mark->mask = AuHfsnMask;
7f207e10
AM
16926+ /*
16927+ * by udba rename or rmdir, aufs assign a new inode to the known
16928+ * h_inode, so specify 1 to allow dups.
16929+ */
c1595e42 16930+ lockdep_off();
acd2b654 16931+ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1);
c1595e42 16932+ lockdep_on();
1716fcea
AM
16933+
16934+ return err;
1facf9fc 16935+}
16936+
7eafdf33 16937+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 16938+{
0c5527e5 16939+ struct fsnotify_mark *mark;
7eafdf33 16940+ unsigned long long ull;
1716fcea 16941+ struct fsnotify_group *group;
7eafdf33
AM
16942+
16943+ ull = atomic64_inc_return(&au_hfsn_ifree);
16944+ BUG_ON(!ull);
953406b4 16945+
0c5527e5 16946+ mark = &hn->hn_mark;
1716fcea
AM
16947+ spin_lock(&mark->lock);
16948+ group = mark->group;
16949+ fsnotify_get_group(group);
16950+ spin_unlock(&mark->lock);
c1595e42 16951+ lockdep_off();
1716fcea 16952+ fsnotify_destroy_mark(mark, group);
5afbbe0d 16953+ fsnotify_put_mark(mark);
1716fcea 16954+ fsnotify_put_group(group);
c1595e42 16955+ lockdep_on();
7f207e10 16956+
7eafdf33
AM
16957+ /* free hn by myself */
16958+ return 0;
1facf9fc 16959+}
16960+
16961+/* ---------------------------------------------------------------------- */
16962+
4a4d8108 16963+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 16964+{
0c5527e5 16965+ struct fsnotify_mark *mark;
1facf9fc 16966+
0c5527e5
AM
16967+ mark = &hinode->hi_notify->hn_mark;
16968+ spin_lock(&mark->lock);
1facf9fc 16969+ if (do_set) {
0c5527e5
AM
16970+ AuDebugOn(mark->mask & AuHfsnMask);
16971+ mark->mask |= AuHfsnMask;
1facf9fc 16972+ } else {
0c5527e5
AM
16973+ AuDebugOn(!(mark->mask & AuHfsnMask));
16974+ mark->mask &= ~AuHfsnMask;
1facf9fc 16975+ }
0c5527e5 16976+ spin_unlock(&mark->lock);
4a4d8108 16977+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 16978+}
16979+
4a4d8108 16980+/* ---------------------------------------------------------------------- */
1facf9fc 16981+
4a4d8108
AM
16982+/* #define AuDbgHnotify */
16983+#ifdef AuDbgHnotify
16984+static char *au_hfsn_name(u32 mask)
16985+{
16986+#ifdef CONFIG_AUFS_DEBUG
c06a8ce3
AM
16987+#define test_ret(flag) \
16988+ do { \
16989+ if (mask & flag) \
16990+ return #flag; \
16991+ } while (0)
4a4d8108
AM
16992+ test_ret(FS_ACCESS);
16993+ test_ret(FS_MODIFY);
16994+ test_ret(FS_ATTRIB);
16995+ test_ret(FS_CLOSE_WRITE);
16996+ test_ret(FS_CLOSE_NOWRITE);
16997+ test_ret(FS_OPEN);
16998+ test_ret(FS_MOVED_FROM);
16999+ test_ret(FS_MOVED_TO);
17000+ test_ret(FS_CREATE);
17001+ test_ret(FS_DELETE);
17002+ test_ret(FS_DELETE_SELF);
17003+ test_ret(FS_MOVE_SELF);
17004+ test_ret(FS_UNMOUNT);
17005+ test_ret(FS_Q_OVERFLOW);
17006+ test_ret(FS_IN_IGNORED);
b912730e 17007+ test_ret(FS_ISDIR);
4a4d8108
AM
17008+ test_ret(FS_IN_ONESHOT);
17009+ test_ret(FS_EVENT_ON_CHILD);
17010+ return "";
17011+#undef test_ret
17012+#else
17013+ return "??";
17014+#endif
1facf9fc 17015+}
4a4d8108 17016+#endif
1facf9fc 17017+
17018+/* ---------------------------------------------------------------------- */
17019+
1716fcea
AM
17020+static void au_hfsn_free_group(struct fsnotify_group *group)
17021+{
17022+ struct au_br_hfsnotify *hfsn = group->private;
17023+
5afbbe0d 17024+ /* AuDbg("here\n"); */
9f237c51 17025+ au_kfree_try_rcu(hfsn);
1716fcea
AM
17026+}
17027+
4a4d8108 17028+static int au_hfsn_handle_event(struct fsnotify_group *group,
fb47a38f 17029+ struct inode *inode,
a2654f78 17030+ u32 mask, const void *data, int data_type,
83b672a5 17031+ const struct qstr *file_name, u32 cookie,
ffa93bbd 17032+ struct fsnotify_iter_info *iter_info)
1facf9fc 17033+{
17034+ int err;
4a4d8108
AM
17035+ struct au_hnotify *hnotify;
17036+ struct inode *h_dir, *h_inode;
cd7a4cd9 17037+ struct fsnotify_mark *inode_mark;
4a4d8108 17038+
fb47a38f 17039+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 17040+
17041+ err = 0;
0c5527e5 17042+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108 17043+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 17044+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 17045+ goto out;
1facf9fc 17046+
fb47a38f
JR
17047+ h_dir = inode;
17048+ h_inode = NULL;
4a4d8108 17049+#ifdef AuDbgHnotify
392086de 17050+ au_debug_on();
fbc438ed
JR
17051+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
17052+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
4a4d8108
AM
17053+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
17054+ h_dir->i_ino, mask, au_hfsn_name(mask),
fbc438ed 17055+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
4a4d8108 17056+ /* WARN_ON(1); */
1facf9fc 17057+ }
392086de 17058+ au_debug_off();
1facf9fc 17059+#endif
4a4d8108 17060+
cd7a4cd9 17061+ inode_mark = fsnotify_iter_inode_mark(iter_info);
0c5527e5
AM
17062+ AuDebugOn(!inode_mark);
17063+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
b62f1e65 17064+ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode);
1facf9fc 17065+
4a4d8108
AM
17066+out:
17067+ return err;
17068+}
1facf9fc 17069+
4a4d8108 17070+static struct fsnotify_ops au_hfsn_ops = {
1716fcea 17071+ .handle_event = au_hfsn_handle_event,
ffa93bbd
AM
17072+ .free_group_priv = au_hfsn_free_group,
17073+ .free_mark = au_hfsn_free_mark
4a4d8108
AM
17074+};
17075+
17076+/* ---------------------------------------------------------------------- */
17077+
027c5e7a
AM
17078+static void au_hfsn_fin_br(struct au_branch *br)
17079+{
1716fcea 17080+ struct au_br_hfsnotify *hfsn;
027c5e7a 17081+
1716fcea 17082+ hfsn = br->br_hfsn;
c1595e42
JR
17083+ if (hfsn) {
17084+ lockdep_off();
1716fcea 17085+ fsnotify_put_group(hfsn->hfsn_group);
c1595e42
JR
17086+ lockdep_on();
17087+ }
027c5e7a
AM
17088+}
17089+
1716fcea 17090+static int au_hfsn_init_br(struct au_branch *br, int perm)
4a4d8108
AM
17091+{
17092+ int err;
1716fcea
AM
17093+ struct fsnotify_group *group;
17094+ struct au_br_hfsnotify *hfsn;
1facf9fc 17095+
4a4d8108 17096+ err = 0;
1716fcea
AM
17097+ br->br_hfsn = NULL;
17098+ if (!au_br_hnotifyable(perm))
027c5e7a 17099+ goto out;
027c5e7a 17100+
1716fcea
AM
17101+ err = -ENOMEM;
17102+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS);
17103+ if (unlikely(!hfsn))
027c5e7a
AM
17104+ goto out;
17105+
1716fcea
AM
17106+ err = 0;
17107+ group = fsnotify_alloc_group(&au_hfsn_ops);
17108+ if (IS_ERR(group)) {
17109+ err = PTR_ERR(group);
0c5527e5 17110+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
1716fcea 17111+ goto out_hfsn;
4a4d8108 17112+ }
1facf9fc 17113+
1716fcea
AM
17114+ group->private = hfsn;
17115+ hfsn->hfsn_group = group;
17116+ br->br_hfsn = hfsn;
17117+ goto out; /* success */
17118+
17119+out_hfsn:
9f237c51 17120+ au_kfree_try_rcu(hfsn);
027c5e7a 17121+out:
1716fcea
AM
17122+ return err;
17123+}
17124+
17125+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
17126+{
17127+ int err;
17128+
17129+ err = 0;
17130+ if (!br->br_hfsn)
17131+ err = au_hfsn_init_br(br, perm);
17132+
1facf9fc 17133+ return err;
17134+}
17135+
7eafdf33
AM
17136+/* ---------------------------------------------------------------------- */
17137+
17138+static void au_hfsn_fin(void)
17139+{
17140+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
17141+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
17142+}
17143+
4a4d8108
AM
17144+const struct au_hnotify_op au_hnotify_op = {
17145+ .ctl = au_hfsn_ctl,
17146+ .alloc = au_hfsn_alloc,
17147+ .free = au_hfsn_free,
1facf9fc 17148+
7eafdf33
AM
17149+ .fin = au_hfsn_fin,
17150+
027c5e7a
AM
17151+ .reset_br = au_hfsn_reset_br,
17152+ .fin_br = au_hfsn_fin_br,
17153+ .init_br = au_hfsn_init_br
4a4d8108 17154+};
7f207e10 17155diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
eca34b5c
AM
17156--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
17157+++ linux/fs/aufs/hfsplus.c 2019-07-11 15:42:14.465571210 +0200
acd2b654 17158@@ -0,0 +1,60 @@
cd7a4cd9 17159+// SPDX-License-Identifier: GPL-2.0
4a4d8108 17160+/*
ba1aed25 17161+ * Copyright (C) 2010-2019 Junjiro R. Okajima
4a4d8108
AM
17162+ *
17163+ * This program, aufs is free software; you can redistribute it and/or modify
17164+ * it under the terms of the GNU General Public License as published by
17165+ * the Free Software Foundation; either version 2 of the License, or
17166+ * (at your option) any later version.
17167+ *
17168+ * This program is distributed in the hope that it will be useful,
17169+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17170+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17171+ * GNU General Public License for more details.
17172+ *
17173+ * You should have received a copy of the GNU General Public License
523b37e3 17174+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 17175+ */
1facf9fc 17176+
4a4d8108 17177+/*
acd2b654 17178+ * special support for filesystems which acquires an inode mutex
4a4d8108
AM
17179+ * at final closing a file, eg, hfsplus.
17180+ *
17181+ * This trick is very simple and stupid, just to open the file before really
acd2b654 17182+ * necessary open to tell hfsplus that this is not the final closing.
4a4d8108
AM
17183+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
17184+ * and au_h_open_post() after releasing it.
17185+ */
1facf9fc 17186+
4a4d8108 17187+#include "aufs.h"
1facf9fc 17188+
392086de
AM
17189+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
17190+ int force_wr)
4a4d8108
AM
17191+{
17192+ struct file *h_file;
17193+ struct dentry *h_dentry;
1facf9fc 17194+
4a4d8108
AM
17195+ h_dentry = au_h_dptr(dentry, bindex);
17196+ AuDebugOn(!h_dentry);
5527c038 17197+ AuDebugOn(d_is_negative(h_dentry));
4a4d8108
AM
17198+
17199+ h_file = NULL;
17200+ if (au_test_hfsplus(h_dentry->d_sb)
7e9cd9fe 17201+ && d_is_reg(h_dentry))
4a4d8108
AM
17202+ h_file = au_h_open(dentry, bindex,
17203+ O_RDONLY | O_NOATIME | O_LARGEFILE,
392086de 17204+ /*file*/NULL, force_wr);
4a4d8108 17205+ return h_file;
1facf9fc 17206+}
17207+
4a4d8108
AM
17208+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
17209+ struct file *h_file)
17210+{
acd2b654
AM
17211+ struct au_branch *br;
17212+
4a4d8108
AM
17213+ if (h_file) {
17214+ fput(h_file);
acd2b654
AM
17215+ br = au_sbr(dentry->d_sb, bindex);
17216+ au_lcnt_dec(&br->br_nfiles);
4a4d8108
AM
17217+ }
17218+}
7f207e10 17219diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
eca34b5c
AM
17220--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
17221+++ linux/fs/aufs/hnotify.c 2019-07-11 15:42:14.465571210 +0200
eca801bf 17222@@ -0,0 +1,721 @@
cd7a4cd9 17223+// SPDX-License-Identifier: GPL-2.0
e49829fe 17224+/*
ba1aed25 17225+ * Copyright (C) 2005-2019 Junjiro R. Okajima
e49829fe
JR
17226+ *
17227+ * This program, aufs is free software; you can redistribute it and/or modify
17228+ * it under the terms of the GNU General Public License as published by
17229+ * the Free Software Foundation; either version 2 of the License, or
17230+ * (at your option) any later version.
17231+ *
17232+ * This program is distributed in the hope that it will be useful,
17233+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17234+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17235+ * GNU General Public License for more details.
17236+ *
17237+ * You should have received a copy of the GNU General Public License
523b37e3 17238+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
17239+ */
17240+
17241+/*
7f207e10 17242+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
17243+ */
17244+
eca801bf 17245+/* #include <linux/iversion.h> */
e49829fe
JR
17246+#include "aufs.h"
17247+
027c5e7a 17248+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
17249+{
17250+ int err;
7f207e10 17251+ struct au_hnotify *hn;
1facf9fc 17252+
4a4d8108
AM
17253+ err = -ENOMEM;
17254+ hn = au_cache_alloc_hnotify();
17255+ if (hn) {
17256+ hn->hn_aufs_inode = inode;
027c5e7a
AM
17257+ hinode->hi_notify = hn;
17258+ err = au_hnotify_op.alloc(hinode);
17259+ AuTraceErr(err);
17260+ if (unlikely(err)) {
17261+ hinode->hi_notify = NULL;
1c60b727 17262+ au_cache_free_hnotify(hn);
4a4d8108
AM
17263+ /*
17264+ * The upper dir was removed by udba, but the same named
acd2b654 17265+ * dir left. In this case, aufs assigns a new inode
4a4d8108 17266+ * number and set the monitor again.
acd2b654 17267+ * For the lower dir, the old monitor is still left.
4a4d8108
AM
17268+ */
17269+ if (err == -EEXIST)
17270+ err = 0;
17271+ }
1308ab2a 17272+ }
1308ab2a 17273+
027c5e7a 17274+ AuTraceErr(err);
1308ab2a 17275+ return err;
dece6358 17276+}
1facf9fc 17277+
4a4d8108 17278+void au_hn_free(struct au_hinode *hinode)
dece6358 17279+{
4a4d8108 17280+ struct au_hnotify *hn;
1facf9fc 17281+
4a4d8108
AM
17282+ hn = hinode->hi_notify;
17283+ if (hn) {
4a4d8108 17284+ hinode->hi_notify = NULL;
7eafdf33 17285+ if (au_hnotify_op.free(hinode, hn))
1c60b727 17286+ au_cache_free_hnotify(hn);
4a4d8108
AM
17287+ }
17288+}
dece6358 17289+
4a4d8108 17290+/* ---------------------------------------------------------------------- */
dece6358 17291+
4a4d8108
AM
17292+void au_hn_ctl(struct au_hinode *hinode, int do_set)
17293+{
17294+ if (hinode->hi_notify)
17295+ au_hnotify_op.ctl(hinode, do_set);
17296+}
17297+
17298+void au_hn_reset(struct inode *inode, unsigned int flags)
17299+{
5afbbe0d 17300+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
17301+ struct inode *hi;
17302+ struct dentry *iwhdentry;
1facf9fc 17303+
5afbbe0d
AM
17304+ bbot = au_ibbot(inode);
17305+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108
AM
17306+ hi = au_h_iptr(inode, bindex);
17307+ if (!hi)
17308+ continue;
1308ab2a 17309+
febd17d6 17310+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */
4a4d8108
AM
17311+ iwhdentry = au_hi_wh(inode, bindex);
17312+ if (iwhdentry)
17313+ dget(iwhdentry);
17314+ au_igrab(hi);
17315+ au_set_h_iptr(inode, bindex, NULL, 0);
17316+ au_set_h_iptr(inode, bindex, au_igrab(hi),
17317+ flags & ~AuHi_XINO);
17318+ iput(hi);
17319+ dput(iwhdentry);
febd17d6 17320+ /* inode_unlock(hi); */
1facf9fc 17321+ }
1facf9fc 17322+}
17323+
1308ab2a 17324+/* ---------------------------------------------------------------------- */
1facf9fc 17325+
4a4d8108 17326+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 17327+{
4a4d8108 17328+ int err;
5afbbe0d 17329+ aufs_bindex_t bindex, bbot, bfound, btop;
4a4d8108 17330+ struct inode *h_i;
1facf9fc 17331+
4a4d8108
AM
17332+ err = 0;
17333+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17334+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17335+ goto out;
17336+ }
1facf9fc 17337+
4a4d8108 17338+ bfound = -1;
5afbbe0d
AM
17339+ bbot = au_ibbot(inode);
17340+ btop = au_ibtop(inode);
4a4d8108 17341+#if 0 /* reserved for future use */
5afbbe0d 17342+ if (bindex == bbot) {
4a4d8108
AM
17343+ /* keep this ino in rename case */
17344+ goto out;
17345+ }
17346+#endif
5afbbe0d 17347+ for (bindex = btop; bindex <= bbot; bindex++)
4a4d8108
AM
17348+ if (au_h_iptr(inode, bindex) == h_inode) {
17349+ bfound = bindex;
17350+ break;
17351+ }
17352+ if (bfound < 0)
1308ab2a 17353+ goto out;
1facf9fc 17354+
5afbbe0d 17355+ for (bindex = btop; bindex <= bbot; bindex++) {
4a4d8108
AM
17356+ h_i = au_h_iptr(inode, bindex);
17357+ if (!h_i)
17358+ continue;
1facf9fc 17359+
4a4d8108
AM
17360+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
17361+ /* ignore this error */
17362+ /* bad action? */
1facf9fc 17363+ }
1facf9fc 17364+
4a4d8108 17365+ /* children inode number will be broken */
1facf9fc 17366+
4f0767ce 17367+out:
4a4d8108
AM
17368+ AuTraceErr(err);
17369+ return err;
1facf9fc 17370+}
17371+
4a4d8108 17372+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 17373+{
4a4d8108
AM
17374+ int err, i, j, ndentry;
17375+ struct au_dcsub_pages dpages;
17376+ struct au_dpage *dpage;
17377+ struct dentry **dentries;
1facf9fc 17378+
4a4d8108
AM
17379+ err = au_dpages_init(&dpages, GFP_NOFS);
17380+ if (unlikely(err))
17381+ goto out;
17382+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
17383+ if (unlikely(err))
17384+ goto out_dpages;
1facf9fc 17385+
4a4d8108
AM
17386+ for (i = 0; i < dpages.ndpage; i++) {
17387+ dpage = dpages.dpages + i;
17388+ dentries = dpage->dentries;
17389+ ndentry = dpage->ndentry;
17390+ for (j = 0; j < ndentry; j++) {
17391+ struct dentry *d;
17392+
17393+ d = dentries[j];
17394+ if (IS_ROOT(d))
17395+ continue;
17396+
4a4d8108 17397+ au_digen_dec(d);
5527c038 17398+ if (d_really_is_positive(d))
4a4d8108
AM
17399+ /* todo: reset children xino?
17400+ cached children only? */
5527c038 17401+ au_iigen_dec(d_inode(d));
1308ab2a 17402+ }
dece6358 17403+ }
1facf9fc 17404+
4f0767ce 17405+out_dpages:
4a4d8108 17406+ au_dpages_free(&dpages);
dece6358 17407+
027c5e7a 17408+#if 0
4a4d8108
AM
17409+ /* discard children */
17410+ dentry_unhash(dentry);
17411+ dput(dentry);
027c5e7a 17412+#endif
4f0767ce 17413+out:
dece6358
AM
17414+ return err;
17415+}
17416+
1308ab2a 17417+/*
4a4d8108 17418+ * return 0 if processed.
1308ab2a 17419+ */
4a4d8108
AM
17420+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
17421+ const unsigned int isdir)
dece6358 17422+{
1308ab2a 17423+ int err;
4a4d8108
AM
17424+ struct dentry *d;
17425+ struct qstr *dname;
1facf9fc 17426+
4a4d8108
AM
17427+ err = 1;
17428+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17429+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17430+ err = 0;
17431+ goto out;
17432+ }
dece6358 17433+
4a4d8108
AM
17434+ if (!isdir) {
17435+ AuDebugOn(!name);
17436+ au_iigen_dec(inode);
027c5e7a 17437+ spin_lock(&inode->i_lock);
c1595e42 17438+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 17439+ spin_lock(&d->d_lock);
4a4d8108
AM
17440+ dname = &d->d_name;
17441+ if (dname->len != nlen
027c5e7a
AM
17442+ && memcmp(dname->name, name, nlen)) {
17443+ spin_unlock(&d->d_lock);
4a4d8108 17444+ continue;
027c5e7a 17445+ }
4a4d8108 17446+ err = 0;
4a4d8108
AM
17447+ au_digen_dec(d);
17448+ spin_unlock(&d->d_lock);
17449+ break;
1facf9fc 17450+ }
027c5e7a 17451+ spin_unlock(&inode->i_lock);
1308ab2a 17452+ } else {
027c5e7a 17453+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
c1595e42 17454+ d = d_find_any_alias(inode);
4a4d8108
AM
17455+ if (!d) {
17456+ au_iigen_dec(inode);
17457+ goto out;
17458+ }
1facf9fc 17459+
027c5e7a 17460+ spin_lock(&d->d_lock);
4a4d8108 17461+ dname = &d->d_name;
027c5e7a
AM
17462+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
17463+ spin_unlock(&d->d_lock);
4a4d8108 17464+ err = hn_gen_tree(d);
027c5e7a
AM
17465+ spin_lock(&d->d_lock);
17466+ }
17467+ spin_unlock(&d->d_lock);
4a4d8108
AM
17468+ dput(d);
17469+ }
1facf9fc 17470+
4f0767ce 17471+out:
4a4d8108 17472+ AuTraceErr(err);
1308ab2a 17473+ return err;
17474+}
dece6358 17475+
4a4d8108 17476+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 17477+{
4a4d8108 17478+ int err;
1facf9fc 17479+
5527c038 17480+ if (IS_ROOT(dentry)) {
0c3ec466 17481+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17482+ return 0;
17483+ }
1308ab2a 17484+
4a4d8108
AM
17485+ err = 0;
17486+ if (!isdir) {
4a4d8108 17487+ au_digen_dec(dentry);
5527c038
JR
17488+ if (d_really_is_positive(dentry))
17489+ au_iigen_dec(d_inode(dentry));
4a4d8108 17490+ } else {
027c5e7a 17491+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
5527c038 17492+ if (d_really_is_positive(dentry))
4a4d8108
AM
17493+ err = hn_gen_tree(dentry);
17494+ }
17495+
17496+ AuTraceErr(err);
17497+ return err;
1facf9fc 17498+}
17499+
4a4d8108 17500+/* ---------------------------------------------------------------------- */
1facf9fc 17501+
4a4d8108
AM
17502+/* hnotify job flags */
17503+#define AuHnJob_XINO0 1
17504+#define AuHnJob_GEN (1 << 1)
17505+#define AuHnJob_DIRENT (1 << 2)
17506+#define AuHnJob_ISDIR (1 << 3)
17507+#define AuHnJob_TRYXINO0 (1 << 4)
17508+#define AuHnJob_MNTPNT (1 << 5)
17509+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
17510+#define au_fset_hnjob(flags, name) \
17511+ do { (flags) |= AuHnJob_##name; } while (0)
17512+#define au_fclr_hnjob(flags, name) \
17513+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 17514+
4a4d8108
AM
17515+enum {
17516+ AuHn_CHILD,
17517+ AuHn_PARENT,
17518+ AuHnLast
17519+};
1facf9fc 17520+
4a4d8108
AM
17521+struct au_hnotify_args {
17522+ struct inode *h_dir, *dir, *h_child_inode;
17523+ u32 mask;
17524+ unsigned int flags[AuHnLast];
17525+ unsigned int h_child_nlen;
17526+ char h_child_name[];
17527+};
1facf9fc 17528+
4a4d8108
AM
17529+struct hn_job_args {
17530+ unsigned int flags;
17531+ struct inode *inode, *h_inode, *dir, *h_dir;
17532+ struct dentry *dentry;
17533+ char *h_name;
17534+ int h_nlen;
17535+};
1308ab2a 17536+
4a4d8108
AM
17537+static int hn_job(struct hn_job_args *a)
17538+{
17539+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
076b876e 17540+ int e;
1308ab2a 17541+
4a4d8108
AM
17542+ /* reset xino */
17543+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
17544+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 17545+
4a4d8108
AM
17546+ if (au_ftest_hnjob(a->flags, TRYXINO0)
17547+ && a->inode
17548+ && a->h_inode) {
be118d29 17549+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
38d290e6
JR
17550+ if (!a->h_inode->i_nlink
17551+ && !(a->h_inode->i_state & I_LINKABLE))
4a4d8108 17552+ hn_xino(a->inode, a->h_inode); /* ignore this error */
3c1bdaff 17553+ inode_unlock_shared(a->h_inode);
1308ab2a 17554+ }
1facf9fc 17555+
4a4d8108
AM
17556+ /* make the generation obsolete */
17557+ if (au_ftest_hnjob(a->flags, GEN)) {
076b876e 17558+ e = -1;
4a4d8108 17559+ if (a->inode)
076b876e 17560+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
4a4d8108 17561+ isdir);
076b876e 17562+ if (e && a->dentry)
4a4d8108
AM
17563+ hn_gen_by_name(a->dentry, isdir);
17564+ /* ignore this error */
1facf9fc 17565+ }
1facf9fc 17566+
4a4d8108
AM
17567+ /* make dir entries obsolete */
17568+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
17569+ struct au_vdir *vdir;
1facf9fc 17570+
4a4d8108
AM
17571+ vdir = au_ivdir(a->inode);
17572+ if (vdir)
17573+ vdir->vd_jiffy = 0;
17574+ /* IMustLock(a->inode); */
be118d29 17575+ /* inode_inc_iversion(a->inode); */
4a4d8108 17576+ }
1facf9fc 17577+
4a4d8108
AM
17578+ /* can do nothing but warn */
17579+ if (au_ftest_hnjob(a->flags, MNTPNT)
17580+ && a->dentry
17581+ && d_mountpoint(a->dentry))
523b37e3 17582+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry);
1facf9fc 17583+
4a4d8108 17584+ return 0;
1308ab2a 17585+}
1facf9fc 17586+
1308ab2a 17587+/* ---------------------------------------------------------------------- */
1facf9fc 17588+
4a4d8108
AM
17589+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
17590+ struct inode *dir)
1308ab2a 17591+{
4a4d8108
AM
17592+ struct dentry *dentry, *d, *parent;
17593+ struct qstr *dname;
1308ab2a 17594+
c1595e42 17595+ parent = d_find_any_alias(dir);
4a4d8108
AM
17596+ if (!parent)
17597+ return NULL;
1308ab2a 17598+
4a4d8108 17599+ dentry = NULL;
027c5e7a 17600+ spin_lock(&parent->d_lock);
c1595e42 17601+ list_for_each_entry(d, &parent->d_subdirs, d_child) {
523b37e3 17602+ /* AuDbg("%pd\n", d); */
027c5e7a 17603+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
17604+ dname = &d->d_name;
17605+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
17606+ goto cont_unlock;
17607+ if (au_di(d))
17608+ au_digen_dec(d);
17609+ else
17610+ goto cont_unlock;
c1595e42 17611+ if (au_dcount(d) > 0) {
027c5e7a 17612+ dentry = dget_dlock(d);
4a4d8108 17613+ spin_unlock(&d->d_lock);
027c5e7a 17614+ break;
dece6358 17615+ }
1facf9fc 17616+
f6b6e03d 17617+cont_unlock:
027c5e7a 17618+ spin_unlock(&d->d_lock);
1308ab2a 17619+ }
027c5e7a 17620+ spin_unlock(&parent->d_lock);
4a4d8108 17621+ dput(parent);
1facf9fc 17622+
4a4d8108
AM
17623+ if (dentry)
17624+ di_write_lock_child(dentry);
1308ab2a 17625+
4a4d8108
AM
17626+ return dentry;
17627+}
dece6358 17628+
4a4d8108
AM
17629+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
17630+ aufs_bindex_t bindex, ino_t h_ino)
17631+{
17632+ struct inode *inode;
17633+ ino_t ino;
17634+ int err;
17635+
17636+ inode = NULL;
17637+ err = au_xino_read(sb, bindex, h_ino, &ino);
17638+ if (!err && ino)
17639+ inode = ilookup(sb, ino);
17640+ if (!inode)
17641+ goto out;
17642+
17643+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17644+ pr_warn("wrong root branch\n");
4a4d8108
AM
17645+ iput(inode);
17646+ inode = NULL;
17647+ goto out;
1308ab2a 17648+ }
17649+
4a4d8108 17650+ ii_write_lock_child(inode);
1308ab2a 17651+
4f0767ce 17652+out:
4a4d8108 17653+ return inode;
dece6358
AM
17654+}
17655+
4a4d8108 17656+static void au_hn_bh(void *_args)
1facf9fc 17657+{
4a4d8108
AM
17658+ struct au_hnotify_args *a = _args;
17659+ struct super_block *sb;
5afbbe0d 17660+ aufs_bindex_t bindex, bbot, bfound;
4a4d8108 17661+ unsigned char xino, try_iput;
1facf9fc 17662+ int err;
1308ab2a 17663+ struct inode *inode;
4a4d8108
AM
17664+ ino_t h_ino;
17665+ struct hn_job_args args;
17666+ struct dentry *dentry;
17667+ struct au_sbinfo *sbinfo;
1facf9fc 17668+
4a4d8108
AM
17669+ AuDebugOn(!_args);
17670+ AuDebugOn(!a->h_dir);
17671+ AuDebugOn(!a->dir);
17672+ AuDebugOn(!a->mask);
17673+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
17674+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
17675+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 17676+
4a4d8108
AM
17677+ inode = NULL;
17678+ dentry = NULL;
17679+ /*
17680+ * do not lock a->dir->i_mutex here
17681+ * because of d_revalidate() may cause a deadlock.
17682+ */
17683+ sb = a->dir->i_sb;
17684+ AuDebugOn(!sb);
17685+ sbinfo = au_sbi(sb);
17686+ AuDebugOn(!sbinfo);
7f207e10 17687+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 17688+
8b6a4947
AM
17689+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
17690+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) {
17691+ case FS_MOVED_FROM:
17692+ case FS_MOVED_TO:
17693+ AuWarn1("DIRREN with UDBA may not work correctly "
17694+ "for the direct rename(2)\n");
17695+ }
17696+
4a4d8108
AM
17697+ ii_read_lock_parent(a->dir);
17698+ bfound = -1;
5afbbe0d
AM
17699+ bbot = au_ibbot(a->dir);
17700+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++)
4a4d8108
AM
17701+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
17702+ bfound = bindex;
17703+ break;
17704+ }
17705+ ii_read_unlock(a->dir);
17706+ if (unlikely(bfound < 0))
17707+ goto out;
1facf9fc 17708+
4a4d8108
AM
17709+ xino = !!au_opt_test(au_mntflags(sb), XINO);
17710+ h_ino = 0;
17711+ if (a->h_child_inode)
17712+ h_ino = a->h_child_inode->i_ino;
1facf9fc 17713+
4a4d8108
AM
17714+ if (a->h_child_nlen
17715+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
17716+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
17717+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
17718+ a->dir);
17719+ try_iput = 0;
5527c038
JR
17720+ if (dentry && d_really_is_positive(dentry))
17721+ inode = d_inode(dentry);
4a4d8108
AM
17722+ if (xino && !inode && h_ino
17723+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
17724+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
17725+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
17726+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
17727+ try_iput = 1;
f0c0a007 17728+ }
1facf9fc 17729+
4a4d8108
AM
17730+ args.flags = a->flags[AuHn_CHILD];
17731+ args.dentry = dentry;
17732+ args.inode = inode;
17733+ args.h_inode = a->h_child_inode;
17734+ args.dir = a->dir;
17735+ args.h_dir = a->h_dir;
17736+ args.h_name = a->h_child_name;
17737+ args.h_nlen = a->h_child_nlen;
17738+ err = hn_job(&args);
17739+ if (dentry) {
027c5e7a 17740+ if (au_di(dentry))
4a4d8108
AM
17741+ di_write_unlock(dentry);
17742+ dput(dentry);
17743+ }
17744+ if (inode && try_iput) {
17745+ ii_write_unlock(inode);
17746+ iput(inode);
17747+ }
1facf9fc 17748+
4a4d8108
AM
17749+ ii_write_lock_parent(a->dir);
17750+ args.flags = a->flags[AuHn_PARENT];
17751+ args.dentry = NULL;
17752+ args.inode = a->dir;
17753+ args.h_inode = a->h_dir;
17754+ args.dir = NULL;
17755+ args.h_dir = NULL;
17756+ args.h_name = NULL;
17757+ args.h_nlen = 0;
17758+ err = hn_job(&args);
17759+ ii_write_unlock(a->dir);
1facf9fc 17760+
4f0767ce 17761+out:
4a4d8108
AM
17762+ iput(a->h_child_inode);
17763+ iput(a->h_dir);
17764+ iput(a->dir);
027c5e7a
AM
17765+ si_write_unlock(sb);
17766+ au_nwt_done(&sbinfo->si_nowait);
9f237c51 17767+ au_kfree_rcu(a);
dece6358 17768+}
1facf9fc 17769+
4a4d8108
AM
17770+/* ---------------------------------------------------------------------- */
17771+
17772+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
b62f1e65 17773+ const struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 17774+{
4a4d8108 17775+ int err, len;
53392da6 17776+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
17777+ unsigned char isdir, isroot, wh;
17778+ struct inode *dir;
17779+ struct au_hnotify_args *args;
17780+ char *p, *h_child_name;
dece6358 17781+
1308ab2a 17782+ err = 0;
4a4d8108
AM
17783+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
17784+ dir = igrab(hnotify->hn_aufs_inode);
17785+ if (!dir)
17786+ goto out;
1facf9fc 17787+
4a4d8108
AM
17788+ isroot = (dir->i_ino == AUFS_ROOT_INO);
17789+ wh = 0;
17790+ h_child_name = (void *)h_child_qstr->name;
17791+ len = h_child_qstr->len;
17792+ if (h_child_name) {
17793+ if (len > AUFS_WH_PFX_LEN
17794+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
17795+ h_child_name += AUFS_WH_PFX_LEN;
17796+ len -= AUFS_WH_PFX_LEN;
17797+ wh = 1;
17798+ }
1facf9fc 17799+ }
dece6358 17800+
4a4d8108
AM
17801+ isdir = 0;
17802+ if (h_child_inode)
17803+ isdir = !!S_ISDIR(h_child_inode->i_mode);
17804+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
17805+ flags[AuHn_CHILD] = 0;
17806+ if (isdir)
17807+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
17808+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
17809+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
fbc438ed 17810+ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) {
4a4d8108
AM
17811+ case FS_MOVED_FROM:
17812+ case FS_MOVED_TO:
17813+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
17814+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
17815+ /*FALLTHROUGH*/
17816+ case FS_CREATE:
fb47a38f 17817+ AuDebugOn(!h_child_name);
4a4d8108 17818+ break;
1facf9fc 17819+
4a4d8108
AM
17820+ case FS_DELETE:
17821+ /*
17822+ * aufs never be able to get this child inode.
17823+ * revalidation should be in d_revalidate()
17824+ * by checking i_nlink, i_generation or d_unhashed().
17825+ */
17826+ AuDebugOn(!h_child_name);
17827+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
17828+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
17829+ break;
dece6358 17830+
4a4d8108
AM
17831+ default:
17832+ AuDebugOn(1);
17833+ }
1308ab2a 17834+
4a4d8108
AM
17835+ if (wh)
17836+ h_child_inode = NULL;
1308ab2a 17837+
4a4d8108
AM
17838+ err = -ENOMEM;
17839+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 17840+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
17841+ if (unlikely(!args)) {
17842+ AuErr1("no memory\n");
17843+ iput(dir);
17844+ goto out;
17845+ }
17846+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
17847+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
17848+ args->mask = mask;
17849+ args->dir = dir;
17850+ args->h_dir = igrab(h_dir);
17851+ if (h_child_inode)
17852+ h_child_inode = igrab(h_child_inode); /* can be NULL */
17853+ args->h_child_inode = h_child_inode;
17854+ args->h_child_nlen = len;
17855+ if (len) {
17856+ p = (void *)args;
17857+ p += sizeof(*args);
17858+ memcpy(p, h_child_name, len);
17859+ p[len] = 0;
1308ab2a 17860+ }
1308ab2a 17861+
38d290e6 17862+ /* NFS fires the event for silly-renamed one from kworker */
53392da6 17863+ f = 0;
38d290e6
JR
17864+ if (!dir->i_nlink
17865+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE)))
53392da6
AM
17866+ f = AuWkq_NEST;
17867+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
17868+ if (unlikely(err)) {
17869+ pr_err("wkq %d\n", err);
17870+ iput(args->h_child_inode);
17871+ iput(args->h_dir);
17872+ iput(args->dir);
9f237c51 17873+ au_kfree_rcu(args);
1facf9fc 17874+ }
1facf9fc 17875+
4a4d8108 17876+out:
1facf9fc 17877+ return err;
17878+}
17879+
027c5e7a
AM
17880+/* ---------------------------------------------------------------------- */
17881+
17882+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
17883+{
17884+ int err;
17885+
17886+ AuDebugOn(!(udba & AuOptMask_UDBA));
17887+
17888+ err = 0;
17889+ if (au_hnotify_op.reset_br)
17890+ err = au_hnotify_op.reset_br(udba, br, perm);
17891+
17892+ return err;
17893+}
17894+
17895+int au_hnotify_init_br(struct au_branch *br, int perm)
17896+{
17897+ int err;
17898+
17899+ err = 0;
17900+ if (au_hnotify_op.init_br)
17901+ err = au_hnotify_op.init_br(br, perm);
17902+
17903+ return err;
17904+}
17905+
17906+void au_hnotify_fin_br(struct au_branch *br)
17907+{
17908+ if (au_hnotify_op.fin_br)
17909+ au_hnotify_op.fin_br(br);
17910+}
17911+
4a4d8108
AM
17912+static void au_hn_destroy_cache(void)
17913+{
1c60b727
AM
17914+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]);
17915+ au_cache[AuCache_HNOTIFY] = NULL;
4a4d8108 17916+}
1308ab2a 17917+
4a4d8108 17918+int __init au_hnotify_init(void)
1facf9fc 17919+{
1308ab2a 17920+ int err;
1308ab2a 17921+
4a4d8108 17922+ err = -ENOMEM;
1c60b727
AM
17923+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify);
17924+ if (au_cache[AuCache_HNOTIFY]) {
027c5e7a
AM
17925+ err = 0;
17926+ if (au_hnotify_op.init)
17927+ err = au_hnotify_op.init();
4a4d8108
AM
17928+ if (unlikely(err))
17929+ au_hn_destroy_cache();
1308ab2a 17930+ }
1308ab2a 17931+ AuTraceErr(err);
4a4d8108 17932+ return err;
1308ab2a 17933+}
17934+
4a4d8108 17935+void au_hnotify_fin(void)
1308ab2a 17936+{
027c5e7a
AM
17937+ if (au_hnotify_op.fin)
17938+ au_hnotify_op.fin();
f0c0a007 17939+
4a4d8108 17940+ /* cf. au_cache_fin() */
1c60b727 17941+ if (au_cache[AuCache_HNOTIFY])
4a4d8108 17942+ au_hn_destroy_cache();
dece6358 17943+}
7f207e10 17944diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
eca34b5c
AM
17945--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
17946+++ linux/fs/aufs/iinfo.c 2019-07-11 15:42:14.468904634 +0200
062440b3 17947@@ -0,0 +1,286 @@
cd7a4cd9 17948+// SPDX-License-Identifier: GPL-2.0
dece6358 17949+/*
ba1aed25 17950+ * Copyright (C) 2005-2019 Junjiro R. Okajima
dece6358
AM
17951+ *
17952+ * This program, aufs is free software; you can redistribute it and/or modify
17953+ * it under the terms of the GNU General Public License as published by
17954+ * the Free Software Foundation; either version 2 of the License, or
17955+ * (at your option) any later version.
17956+ *
17957+ * This program is distributed in the hope that it will be useful,
17958+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17959+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17960+ * GNU General Public License for more details.
17961+ *
17962+ * You should have received a copy of the GNU General Public License
523b37e3 17963+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 17964+ */
1facf9fc 17965+
dece6358 17966+/*
4a4d8108 17967+ * inode private data
dece6358 17968+ */
1facf9fc 17969+
1308ab2a 17970+#include "aufs.h"
1facf9fc 17971+
4a4d8108 17972+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 17973+{
4a4d8108 17974+ struct inode *h_inode;
5afbbe0d 17975+ struct au_hinode *hinode;
1facf9fc 17976+
4a4d8108 17977+ IiMustAnyLock(inode);
1facf9fc 17978+
5afbbe0d
AM
17979+ hinode = au_hinode(au_ii(inode), bindex);
17980+ h_inode = hinode->hi_inode;
4a4d8108
AM
17981+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
17982+ return h_inode;
17983+}
1facf9fc 17984+
4a4d8108
AM
17985+/* todo: hard/soft set? */
17986+void au_hiput(struct au_hinode *hinode)
17987+{
17988+ au_hn_free(hinode);
17989+ dput(hinode->hi_whdentry);
17990+ iput(hinode->hi_inode);
17991+}
1facf9fc 17992+
4a4d8108
AM
17993+unsigned int au_hi_flags(struct inode *inode, int isdir)
17994+{
17995+ unsigned int flags;
17996+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 17997+
4a4d8108
AM
17998+ flags = 0;
17999+ if (au_opt_test(mnt_flags, XINO))
18000+ au_fset_hi(flags, XINO);
18001+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
18002+ au_fset_hi(flags, HNOTIFY);
18003+ return flags;
1facf9fc 18004+}
18005+
4a4d8108
AM
18006+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
18007+ struct inode *h_inode, unsigned int flags)
1308ab2a 18008+{
4a4d8108
AM
18009+ struct au_hinode *hinode;
18010+ struct inode *hi;
18011+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 18012+
4a4d8108 18013+ IiMustWriteLock(inode);
dece6358 18014+
5afbbe0d 18015+ hinode = au_hinode(iinfo, bindex);
4a4d8108
AM
18016+ hi = hinode->hi_inode;
18017+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
18018+
18019+ if (hi)
18020+ au_hiput(hinode);
18021+ hinode->hi_inode = h_inode;
18022+ if (h_inode) {
18023+ int err;
18024+ struct super_block *sb = inode->i_sb;
18025+ struct au_branch *br;
18026+
027c5e7a
AM
18027+ AuDebugOn(inode->i_mode
18028+ && (h_inode->i_mode & S_IFMT)
18029+ != (inode->i_mode & S_IFMT));
5afbbe0d 18030+ if (bindex == iinfo->ii_btop)
4a4d8108
AM
18031+ au_cpup_igen(inode, h_inode);
18032+ br = au_sbr(sb, bindex);
18033+ hinode->hi_id = br->br_id;
18034+ if (au_ftest_hi(flags, XINO)) {
18035+ err = au_xino_write(sb, bindex, h_inode->i_ino,
18036+ inode->i_ino);
18037+ if (unlikely(err))
18038+ AuIOErr1("failed au_xino_write() %d\n", err);
18039+ }
18040+
18041+ if (au_ftest_hi(flags, HNOTIFY)
18042+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 18043+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
18044+ if (unlikely(err))
18045+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 18046+ }
18047+ }
4a4d8108 18048+}
dece6358 18049+
4a4d8108
AM
18050+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
18051+ struct dentry *h_wh)
18052+{
18053+ struct au_hinode *hinode;
dece6358 18054+
4a4d8108
AM
18055+ IiMustWriteLock(inode);
18056+
5afbbe0d 18057+ hinode = au_hinode(au_ii(inode), bindex);
4a4d8108
AM
18058+ AuDebugOn(hinode->hi_whdentry);
18059+ hinode->hi_whdentry = h_wh;
1facf9fc 18060+}
18061+
537831f9 18062+void au_update_iigen(struct inode *inode, int half)
1308ab2a 18063+{
537831f9
AM
18064+ struct au_iinfo *iinfo;
18065+ struct au_iigen *iigen;
18066+ unsigned int sigen;
18067+
18068+ sigen = au_sigen(inode->i_sb);
18069+ iinfo = au_ii(inode);
18070+ iigen = &iinfo->ii_generation;
be52b249 18071+ spin_lock(&iigen->ig_spin);
537831f9
AM
18072+ iigen->ig_generation = sigen;
18073+ if (half)
18074+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED);
18075+ else
18076+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED);
be52b249 18077+ spin_unlock(&iigen->ig_spin);
4a4d8108 18078+}
1facf9fc 18079+
4a4d8108
AM
18080+/* it may be called at remount time, too */
18081+void au_update_ibrange(struct inode *inode, int do_put_zero)
18082+{
18083+ struct au_iinfo *iinfo;
5afbbe0d 18084+ aufs_bindex_t bindex, bbot;
1facf9fc 18085+
5afbbe0d 18086+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 18087+ IiMustWriteLock(inode);
1facf9fc 18088+
5afbbe0d
AM
18089+ iinfo = au_ii(inode);
18090+ if (do_put_zero && iinfo->ii_btop >= 0) {
18091+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
18092+ bindex++) {
18093+ struct inode *h_i;
1facf9fc 18094+
5afbbe0d 18095+ h_i = au_hinode(iinfo, bindex)->hi_inode;
38d290e6
JR
18096+ if (h_i
18097+ && !h_i->i_nlink
18098+ && !(h_i->i_state & I_LINKABLE))
027c5e7a
AM
18099+ au_set_h_iptr(inode, bindex, NULL, 0);
18100+ }
4a4d8108
AM
18101+ }
18102+
5afbbe0d
AM
18103+ iinfo->ii_btop = -1;
18104+ iinfo->ii_bbot = -1;
18105+ bbot = au_sbbot(inode->i_sb);
18106+ for (bindex = 0; bindex <= bbot; bindex++)
18107+ if (au_hinode(iinfo, bindex)->hi_inode) {
18108+ iinfo->ii_btop = bindex;
4a4d8108 18109+ break;
027c5e7a 18110+ }
5afbbe0d
AM
18111+ if (iinfo->ii_btop >= 0)
18112+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--)
18113+ if (au_hinode(iinfo, bindex)->hi_inode) {
18114+ iinfo->ii_bbot = bindex;
027c5e7a
AM
18115+ break;
18116+ }
5afbbe0d 18117+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot);
1308ab2a 18118+}
1facf9fc 18119+
dece6358 18120+/* ---------------------------------------------------------------------- */
1facf9fc 18121+
4a4d8108 18122+void au_icntnr_init_once(void *_c)
dece6358 18123+{
4a4d8108
AM
18124+ struct au_icntnr *c = _c;
18125+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 18126+
be52b249 18127+ spin_lock_init(&iinfo->ii_generation.ig_spin);
4a4d8108
AM
18128+ au_rw_init(&iinfo->ii_rwsem);
18129+ inode_init_once(&c->vfs_inode);
18130+}
1facf9fc 18131+
5afbbe0d
AM
18132+void au_hinode_init(struct au_hinode *hinode)
18133+{
18134+ hinode->hi_inode = NULL;
18135+ hinode->hi_id = -1;
18136+ au_hn_init(hinode);
18137+ hinode->hi_whdentry = NULL;
18138+}
18139+
4a4d8108
AM
18140+int au_iinfo_init(struct inode *inode)
18141+{
18142+ struct au_iinfo *iinfo;
18143+ struct super_block *sb;
5afbbe0d 18144+ struct au_hinode *hi;
4a4d8108 18145+ int nbr, i;
1facf9fc 18146+
4a4d8108
AM
18147+ sb = inode->i_sb;
18148+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
5afbbe0d 18149+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
18150+ if (unlikely(nbr <= 0))
18151+ nbr = 1;
5afbbe0d
AM
18152+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
18153+ if (hi) {
acd2b654 18154+ au_lcnt_inc(&au_sbi(sb)->si_ninodes);
5afbbe0d
AM
18155+
18156+ iinfo->ii_hinode = hi;
18157+ for (i = 0; i < nbr; i++, hi++)
18158+ au_hinode_init(hi);
1facf9fc 18159+
537831f9 18160+ iinfo->ii_generation.ig_generation = au_sigen(sb);
5afbbe0d
AM
18161+ iinfo->ii_btop = -1;
18162+ iinfo->ii_bbot = -1;
4a4d8108
AM
18163+ iinfo->ii_vdir = NULL;
18164+ return 0;
1308ab2a 18165+ }
4a4d8108
AM
18166+ return -ENOMEM;
18167+}
1facf9fc 18168+
e2f27e51 18169+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink)
4a4d8108 18170+{
5afbbe0d 18171+ int err, i;
4a4d8108 18172+ struct au_hinode *hip;
1facf9fc 18173+
4a4d8108
AM
18174+ AuRwMustWriteLock(&iinfo->ii_rwsem);
18175+
18176+ err = -ENOMEM;
e2f27e51
AM
18177+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS,
18178+ may_shrink);
4a4d8108
AM
18179+ if (hip) {
18180+ iinfo->ii_hinode = hip;
5afbbe0d
AM
18181+ i = iinfo->ii_bbot + 1;
18182+ hip += i;
18183+ for (; i < nbr; i++, hip++)
18184+ au_hinode_init(hip);
4a4d8108 18185+ err = 0;
1308ab2a 18186+ }
4a4d8108 18187+
1308ab2a 18188+ return err;
1facf9fc 18189+}
18190+
4a4d8108 18191+void au_iinfo_fin(struct inode *inode)
1facf9fc 18192+{
4a4d8108
AM
18193+ struct au_iinfo *iinfo;
18194+ struct au_hinode *hi;
18195+ struct super_block *sb;
5afbbe0d 18196+ aufs_bindex_t bindex, bbot;
b752ccd1 18197+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 18198+
5afbbe0d 18199+ AuDebugOn(au_is_bad_inode(inode));
1308ab2a 18200+
b752ccd1 18201+ sb = inode->i_sb;
acd2b654 18202+ au_lcnt_dec(&au_sbi(sb)->si_ninodes);
b752ccd1
AM
18203+ if (si_pid_test(sb))
18204+ au_xino_delete_inode(inode, unlinked);
18205+ else {
18206+ /*
18207+ * it is safe to hide the dependency between sbinfo and
18208+ * sb->s_umount.
18209+ */
18210+ lockdep_off();
18211+ si_noflush_read_lock(sb);
18212+ au_xino_delete_inode(inode, unlinked);
18213+ si_read_unlock(sb);
18214+ lockdep_on();
18215+ }
18216+
5afbbe0d 18217+ iinfo = au_ii(inode);
4a4d8108 18218+ if (iinfo->ii_vdir)
1c60b727 18219+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 18220+
5afbbe0d 18221+ bindex = iinfo->ii_btop;
b752ccd1 18222+ if (bindex >= 0) {
5afbbe0d
AM
18223+ hi = au_hinode(iinfo, bindex);
18224+ bbot = iinfo->ii_bbot;
18225+ while (bindex++ <= bbot) {
b752ccd1 18226+ if (hi->hi_inode)
4a4d8108 18227+ au_hiput(hi);
4a4d8108
AM
18228+ hi++;
18229+ }
18230+ }
9f237c51 18231+ au_kfree_rcu(iinfo->ii_hinode);
4a4d8108 18232+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 18233+}
7f207e10 18234diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
eca34b5c
AM
18235--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
18236+++ linux/fs/aufs/inode.c 2019-07-11 15:42:14.468904634 +0200
eca801bf 18237@@ -0,0 +1,529 @@
cd7a4cd9 18238+// SPDX-License-Identifier: GPL-2.0
4a4d8108 18239+/*
ba1aed25 18240+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
18241+ *
18242+ * This program, aufs is free software; you can redistribute it and/or modify
18243+ * it under the terms of the GNU General Public License as published by
18244+ * the Free Software Foundation; either version 2 of the License, or
18245+ * (at your option) any later version.
18246+ *
18247+ * This program is distributed in the hope that it will be useful,
18248+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18249+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18250+ * GNU General Public License for more details.
18251+ *
18252+ * You should have received a copy of the GNU General Public License
523b37e3 18253+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18254+ */
1facf9fc 18255+
4a4d8108
AM
18256+/*
18257+ * inode functions
18258+ */
1facf9fc 18259+
eca801bf 18260+#include <linux/iversion.h>
4a4d8108 18261+#include "aufs.h"
1308ab2a 18262+
4a4d8108
AM
18263+struct inode *au_igrab(struct inode *inode)
18264+{
18265+ if (inode) {
18266+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 18267+ ihold(inode);
1facf9fc 18268+ }
4a4d8108
AM
18269+ return inode;
18270+}
1facf9fc 18271+
4a4d8108
AM
18272+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
18273+{
18274+ au_cpup_attr_all(inode, /*force*/0);
537831f9 18275+ au_update_iigen(inode, /*half*/1);
4a4d8108 18276+ if (do_version)
be118d29 18277+ inode_inc_iversion(inode);
dece6358 18278+}
1facf9fc 18279+
027c5e7a 18280+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 18281+{
e2f27e51 18282+ int err, e, nbr;
027c5e7a 18283+ umode_t type;
4a4d8108 18284+ aufs_bindex_t bindex, new_bindex;
1308ab2a 18285+ struct super_block *sb;
4a4d8108 18286+ struct au_iinfo *iinfo;
027c5e7a 18287+ struct au_hinode *p, *q, tmp;
1facf9fc 18288+
5afbbe0d 18289+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 18290+ IiMustWriteLock(inode);
1facf9fc 18291+
027c5e7a 18292+ *update = 0;
4a4d8108 18293+ sb = inode->i_sb;
e2f27e51 18294+ nbr = au_sbbot(sb) + 1;
027c5e7a 18295+ type = inode->i_mode & S_IFMT;
4a4d8108 18296+ iinfo = au_ii(inode);
e2f27e51 18297+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0);
4a4d8108 18298+ if (unlikely(err))
1308ab2a 18299+ goto out;
1facf9fc 18300+
5afbbe0d
AM
18301+ AuDebugOn(iinfo->ii_btop < 0);
18302+ p = au_hinode(iinfo, iinfo->ii_btop);
18303+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
18304+ bindex++, p++) {
18305+ if (!p->hi_inode)
18306+ continue;
1facf9fc 18307+
027c5e7a 18308+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
18309+ new_bindex = au_br_index(sb, p->hi_id);
18310+ if (new_bindex == bindex)
18311+ continue;
1facf9fc 18312+
4a4d8108 18313+ if (new_bindex < 0) {
027c5e7a 18314+ *update = 1;
4a4d8108
AM
18315+ au_hiput(p);
18316+ p->hi_inode = NULL;
18317+ continue;
1308ab2a 18318+ }
4a4d8108 18319+
5afbbe0d
AM
18320+ if (new_bindex < iinfo->ii_btop)
18321+ iinfo->ii_btop = new_bindex;
18322+ if (iinfo->ii_bbot < new_bindex)
18323+ iinfo->ii_bbot = new_bindex;
4a4d8108 18324+ /* swap two lower inode, and loop again */
5afbbe0d 18325+ q = au_hinode(iinfo, new_bindex);
4a4d8108
AM
18326+ tmp = *q;
18327+ *q = *p;
18328+ *p = tmp;
18329+ if (tmp.hi_inode) {
18330+ bindex--;
18331+ p--;
1308ab2a 18332+ }
18333+ }
4a4d8108 18334+ au_update_ibrange(inode, /*do_put_zero*/0);
e2f27e51 18335+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */
4a4d8108
AM
18336+ e = au_dy_irefresh(inode);
18337+ if (unlikely(e && !err))
18338+ err = e;
1facf9fc 18339+
4f0767ce 18340+out:
027c5e7a
AM
18341+ AuTraceErr(err);
18342+ return err;
18343+}
18344+
b95c5147
AM
18345+void au_refresh_iop(struct inode *inode, int force_getattr)
18346+{
18347+ int type;
18348+ struct au_sbinfo *sbi = au_sbi(inode->i_sb);
18349+ const struct inode_operations *iop
18350+ = force_getattr ? aufs_iop : sbi->si_iop_array;
18351+
18352+ if (inode->i_op == iop)
18353+ return;
18354+
18355+ switch (inode->i_mode & S_IFMT) {
18356+ case S_IFDIR:
18357+ type = AuIop_DIR;
18358+ break;
18359+ case S_IFLNK:
18360+ type = AuIop_SYMLINK;
18361+ break;
18362+ default:
18363+ type = AuIop_OTHER;
18364+ break;
18365+ }
18366+
18367+ inode->i_op = iop + type;
18368+ /* unnecessary smp_wmb() */
18369+}
18370+
027c5e7a
AM
18371+int au_refresh_hinode_self(struct inode *inode)
18372+{
18373+ int err, update;
18374+
18375+ err = au_ii_refresh(inode, &update);
18376+ if (!err)
18377+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
18378+
18379+ AuTraceErr(err);
4a4d8108
AM
18380+ return err;
18381+}
1facf9fc 18382+
4a4d8108
AM
18383+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
18384+{
027c5e7a 18385+ int err, e, update;
4a4d8108 18386+ unsigned int flags;
027c5e7a 18387+ umode_t mode;
5afbbe0d 18388+ aufs_bindex_t bindex, bbot;
027c5e7a 18389+ unsigned char isdir;
4a4d8108
AM
18390+ struct au_hinode *p;
18391+ struct au_iinfo *iinfo;
1facf9fc 18392+
027c5e7a 18393+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
18394+ if (unlikely(err))
18395+ goto out;
18396+
18397+ update = 0;
18398+ iinfo = au_ii(inode);
5afbbe0d 18399+ p = au_hinode(iinfo, iinfo->ii_btop);
027c5e7a
AM
18400+ mode = (inode->i_mode & S_IFMT);
18401+ isdir = S_ISDIR(mode);
4a4d8108 18402+ flags = au_hi_flags(inode, isdir);
5afbbe0d
AM
18403+ bbot = au_dbbot(dentry);
18404+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
5527c038 18405+ struct inode *h_i, *h_inode;
4a4d8108
AM
18406+ struct dentry *h_d;
18407+
18408+ h_d = au_h_dptr(dentry, bindex);
5527c038 18409+ if (!h_d || d_is_negative(h_d))
4a4d8108
AM
18410+ continue;
18411+
5527c038
JR
18412+ h_inode = d_inode(h_d);
18413+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT));
5afbbe0d 18414+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) {
4a4d8108
AM
18415+ h_i = au_h_iptr(inode, bindex);
18416+ if (h_i) {
5527c038 18417+ if (h_i == h_inode)
4a4d8108
AM
18418+ continue;
18419+ err = -EIO;
18420+ break;
18421+ }
18422+ }
5afbbe0d
AM
18423+ if (bindex < iinfo->ii_btop)
18424+ iinfo->ii_btop = bindex;
18425+ if (iinfo->ii_bbot < bindex)
18426+ iinfo->ii_bbot = bindex;
5527c038 18427+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags);
4a4d8108 18428+ update = 1;
1308ab2a 18429+ }
4a4d8108
AM
18430+ au_update_ibrange(inode, /*do_put_zero*/0);
18431+ e = au_dy_irefresh(inode);
18432+ if (unlikely(e && !err))
18433+ err = e;
027c5e7a
AM
18434+ if (!err)
18435+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 18436+
4f0767ce 18437+out:
4a4d8108 18438+ AuTraceErr(err);
1308ab2a 18439+ return err;
dece6358
AM
18440+}
18441+
4a4d8108 18442+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 18443+{
4a4d8108
AM
18444+ int err;
18445+ unsigned int flags;
18446+ umode_t mode;
5afbbe0d 18447+ aufs_bindex_t bindex, btop, btail;
4a4d8108
AM
18448+ unsigned char isdir;
18449+ struct dentry *h_dentry;
18450+ struct inode *h_inode;
18451+ struct au_iinfo *iinfo;
b95c5147 18452+ struct inode_operations *iop;
dece6358 18453+
4a4d8108 18454+ IiMustWriteLock(inode);
dece6358 18455+
4a4d8108
AM
18456+ err = 0;
18457+ isdir = 0;
b95c5147 18458+ iop = au_sbi(inode->i_sb)->si_iop_array;
5afbbe0d
AM
18459+ btop = au_dbtop(dentry);
18460+ h_dentry = au_h_dptr(dentry, btop);
5527c038 18461+ h_inode = d_inode(h_dentry);
4a4d8108
AM
18462+ mode = h_inode->i_mode;
18463+ switch (mode & S_IFMT) {
18464+ case S_IFREG:
18465+ btail = au_dbtail(dentry);
b95c5147 18466+ inode->i_op = iop + AuIop_OTHER;
4a4d8108 18467+ inode->i_fop = &aufs_file_fop;
5afbbe0d 18468+ err = au_dy_iaop(inode, btop, h_inode);
4a4d8108
AM
18469+ if (unlikely(err))
18470+ goto out;
18471+ break;
18472+ case S_IFDIR:
18473+ isdir = 1;
18474+ btail = au_dbtaildir(dentry);
b95c5147 18475+ inode->i_op = iop + AuIop_DIR;
4a4d8108
AM
18476+ inode->i_fop = &aufs_dir_fop;
18477+ break;
18478+ case S_IFLNK:
18479+ btail = au_dbtail(dentry);
b95c5147 18480+ inode->i_op = iop + AuIop_SYMLINK;
4a4d8108
AM
18481+ break;
18482+ case S_IFBLK:
18483+ case S_IFCHR:
18484+ case S_IFIFO:
18485+ case S_IFSOCK:
18486+ btail = au_dbtail(dentry);
b95c5147 18487+ inode->i_op = iop + AuIop_OTHER;
38d290e6 18488+ init_special_inode(inode, mode, h_inode->i_rdev);
4a4d8108
AM
18489+ break;
18490+ default:
18491+ AuIOErr("Unknown file type 0%o\n", mode);
18492+ err = -EIO;
1308ab2a 18493+ goto out;
4a4d8108 18494+ }
dece6358 18495+
4a4d8108
AM
18496+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
18497+ flags = au_hi_flags(inode, isdir);
18498+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
18499+ && au_ftest_hi(flags, HNOTIFY)
18500+ && dentry->d_name.len > AUFS_WH_PFX_LEN
18501+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
18502+ au_fclr_hi(flags, HNOTIFY);
18503+ iinfo = au_ii(inode);
5afbbe0d
AM
18504+ iinfo->ii_btop = btop;
18505+ iinfo->ii_bbot = btail;
18506+ for (bindex = btop; bindex <= btail; bindex++) {
4a4d8108
AM
18507+ h_dentry = au_h_dptr(dentry, bindex);
18508+ if (h_dentry)
18509+ au_set_h_iptr(inode, bindex,
5527c038 18510+ au_igrab(d_inode(h_dentry)), flags);
4a4d8108
AM
18511+ }
18512+ au_cpup_attr_all(inode, /*force*/1);
c1595e42
JR
18513+ /*
18514+ * to force calling aufs_get_acl() every time,
18515+ * do not call cache_no_acl() for aufs inode.
18516+ */
dece6358 18517+
4f0767ce 18518+out:
4a4d8108
AM
18519+ return err;
18520+}
dece6358 18521+
027c5e7a
AM
18522+/*
18523+ * successful returns with iinfo write_locked
18524+ * minus: errno
18525+ * zero: success, matched
18526+ * plus: no error, but unmatched
18527+ */
18528+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
18529+{
18530+ int err;
cfc41e69 18531+ unsigned int gen, igflags;
5afbbe0d 18532+ aufs_bindex_t bindex, bbot;
4a4d8108 18533+ struct inode *h_inode, *h_dinode;
5527c038 18534+ struct dentry *h_dentry;
dece6358 18535+
4a4d8108
AM
18536+ /*
18537+ * before this function, if aufs got any iinfo lock, it must be only
18538+ * one, the parent dir.
18539+ * it can happen by UDBA and the obsoleted inode number.
18540+ */
18541+ err = -EIO;
18542+ if (unlikely(inode->i_ino == parent_ino(dentry)))
18543+ goto out;
18544+
027c5e7a 18545+ err = 1;
4a4d8108 18546+ ii_write_lock_new_child(inode);
5afbbe0d 18547+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry));
5527c038 18548+ h_dinode = d_inode(h_dentry);
5afbbe0d
AM
18549+ bbot = au_ibbot(inode);
18550+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108 18551+ h_inode = au_h_iptr(inode, bindex);
537831f9
AM
18552+ if (!h_inode || h_inode != h_dinode)
18553+ continue;
18554+
18555+ err = 0;
cfc41e69 18556+ gen = au_iigen(inode, &igflags);
537831f9 18557+ if (gen == au_digen(dentry)
cfc41e69 18558+ && !au_ig_ftest(igflags, HALF_REFRESHED))
4a4d8108 18559+ break;
537831f9
AM
18560+
18561+ /* fully refresh inode using dentry */
18562+ err = au_refresh_hinode(inode, dentry);
18563+ if (!err)
18564+ au_update_iigen(inode, /*half*/0);
18565+ break;
1facf9fc 18566+ }
dece6358 18567+
4a4d8108
AM
18568+ if (unlikely(err))
18569+ ii_write_unlock(inode);
4f0767ce 18570+out:
1facf9fc 18571+ return err;
18572+}
1facf9fc 18573+
4a4d8108
AM
18574+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18575+ unsigned int d_type, ino_t *ino)
1facf9fc 18576+{
521ced18
JR
18577+ int err, idx;
18578+ const int isnondir = d_type != DT_DIR;
1facf9fc 18579+
b752ccd1 18580+ /* prevent hardlinked inode number from race condition */
521ced18
JR
18581+ if (isnondir) {
18582+ err = au_xinondir_enter(sb, bindex, h_ino, &idx);
18583+ if (unlikely(err))
18584+ goto out;
4a4d8108 18585+ }
521ced18 18586+
4a4d8108
AM
18587+ err = au_xino_read(sb, bindex, h_ino, ino);
18588+ if (unlikely(err))
521ced18 18589+ goto out_xinondir;
1308ab2a 18590+
4a4d8108
AM
18591+ if (!*ino) {
18592+ err = -EIO;
18593+ *ino = au_xino_new_ino(sb);
18594+ if (unlikely(!*ino))
521ced18 18595+ goto out_xinondir;
4a4d8108
AM
18596+ err = au_xino_write(sb, bindex, h_ino, *ino);
18597+ if (unlikely(err))
521ced18 18598+ goto out_xinondir;
1308ab2a 18599+ }
1facf9fc 18600+
521ced18
JR
18601+out_xinondir:
18602+ if (isnondir && idx >= 0)
18603+ au_xinondir_leave(sb, bindex, h_ino, idx);
4f0767ce 18604+out:
1facf9fc 18605+ return err;
18606+}
18607+
4a4d8108
AM
18608+/* successful returns with iinfo write_locked */
18609+/* todo: return with unlocked? */
18610+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 18611+{
5527c038 18612+ struct inode *inode, *h_inode;
4a4d8108
AM
18613+ struct dentry *h_dentry;
18614+ struct super_block *sb;
18615+ ino_t h_ino, ino;
521ced18 18616+ int err, idx, hlinked;
5afbbe0d 18617+ aufs_bindex_t btop;
1facf9fc 18618+
4a4d8108 18619+ sb = dentry->d_sb;
5afbbe0d
AM
18620+ btop = au_dbtop(dentry);
18621+ h_dentry = au_h_dptr(dentry, btop);
5527c038
JR
18622+ h_inode = d_inode(h_dentry);
18623+ h_ino = h_inode->i_ino;
521ced18 18624+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1;
b752ccd1 18625+
521ced18 18626+new_ino:
b752ccd1
AM
18627+ /*
18628+ * stop 'race'-ing between hardlinks under different
18629+ * parents.
18630+ */
521ced18
JR
18631+ if (hlinked) {
18632+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18633+ inode = ERR_PTR(err);
18634+ if (unlikely(err))
18635+ goto out;
18636+ }
b752ccd1 18637+
5afbbe0d 18638+ err = au_xino_read(sb, btop, h_ino, &ino);
4a4d8108
AM
18639+ inode = ERR_PTR(err);
18640+ if (unlikely(err))
521ced18 18641+ goto out_xinondir;
b752ccd1 18642+
4a4d8108
AM
18643+ if (!ino) {
18644+ ino = au_xino_new_ino(sb);
18645+ if (unlikely(!ino)) {
18646+ inode = ERR_PTR(-EIO);
521ced18 18647+ goto out_xinondir;
dece6358
AM
18648+ }
18649+ }
1facf9fc 18650+
4a4d8108
AM
18651+ AuDbg("i%lu\n", (unsigned long)ino);
18652+ inode = au_iget_locked(sb, ino);
18653+ err = PTR_ERR(inode);
18654+ if (IS_ERR(inode))
521ced18 18655+ goto out_xinondir;
1facf9fc 18656+
4a4d8108
AM
18657+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
18658+ if (inode->i_state & I_NEW) {
18659+ ii_write_lock_new_child(inode);
18660+ err = set_inode(inode, dentry);
18661+ if (!err) {
18662+ unlock_new_inode(inode);
521ced18 18663+ goto out_xinondir; /* success */
4a4d8108 18664+ }
1308ab2a 18665+
027c5e7a
AM
18666+ /*
18667+ * iget_failed() calls iput(), but we need to call
18668+ * ii_write_unlock() after iget_failed(). so dirty hack for
18669+ * i_count.
18670+ */
18671+ atomic_inc(&inode->i_count);
4a4d8108 18672+ iget_failed(inode);
027c5e7a 18673+ ii_write_unlock(inode);
5afbbe0d 18674+ au_xino_write(sb, btop, h_ino, /*ino*/0);
027c5e7a
AM
18675+ /* ignore this error */
18676+ goto out_iput;
18677+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
18678+ /*
18679+ * horrible race condition between lookup, readdir and copyup
18680+ * (or something).
18681+ */
521ced18
JR
18682+ if (hlinked && idx >= 0)
18683+ au_xinondir_leave(sb, btop, h_ino, idx);
027c5e7a
AM
18684+ err = reval_inode(inode, dentry);
18685+ if (unlikely(err < 0)) {
521ced18 18686+ hlinked = 0;
027c5e7a
AM
18687+ goto out_iput;
18688+ }
521ced18 18689+ if (!err)
4a4d8108 18690+ goto out; /* success */
521ced18
JR
18691+ else if (hlinked && idx >= 0) {
18692+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18693+ if (unlikely(err)) {
18694+ iput(inode);
18695+ inode = ERR_PTR(err);
18696+ goto out;
18697+ }
18698+ }
4a4d8108
AM
18699+ }
18700+
5527c038 18701+ if (unlikely(au_test_fs_unique_ino(h_inode)))
4a4d8108 18702+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
523b37e3 18703+ " b%d, %s, %pd, hi%lu, i%lu.\n",
5afbbe0d 18704+ btop, au_sbtype(h_dentry->d_sb), dentry,
4a4d8108
AM
18705+ (unsigned long)h_ino, (unsigned long)ino);
18706+ ino = 0;
5afbbe0d 18707+ err = au_xino_write(sb, btop, h_ino, /*ino*/0);
4a4d8108
AM
18708+ if (!err) {
18709+ iput(inode);
521ced18
JR
18710+ if (hlinked && idx >= 0)
18711+ au_xinondir_leave(sb, btop, h_ino, idx);
4a4d8108
AM
18712+ goto new_ino;
18713+ }
1308ab2a 18714+
4f0767ce 18715+out_iput:
4a4d8108 18716+ iput(inode);
4a4d8108 18717+ inode = ERR_PTR(err);
521ced18
JR
18718+out_xinondir:
18719+ if (hlinked && idx >= 0)
18720+ au_xinondir_leave(sb, btop, h_ino, idx);
4f0767ce 18721+out:
4a4d8108 18722+ return inode;
1facf9fc 18723+}
18724+
4a4d8108 18725+/* ---------------------------------------------------------------------- */
1facf9fc 18726+
4a4d8108
AM
18727+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18728+ struct inode *inode)
18729+{
18730+ int err;
076b876e 18731+ struct inode *hi;
1facf9fc 18732+
4a4d8108 18733+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 18734+
4a4d8108
AM
18735+ /* pseudo-link after flushed may happen out of bounds */
18736+ if (!err
18737+ && inode
5afbbe0d
AM
18738+ && au_ibtop(inode) <= bindex
18739+ && bindex <= au_ibbot(inode)) {
4a4d8108
AM
18740+ /*
18741+ * permission check is unnecessary since vfsub routine
18742+ * will be called later
18743+ */
076b876e 18744+ hi = au_h_iptr(inode, bindex);
4a4d8108
AM
18745+ if (hi)
18746+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 18747+ }
18748+
4a4d8108
AM
18749+ return err;
18750+}
dece6358 18751+
4a4d8108
AM
18752+int au_test_h_perm(struct inode *h_inode, int mask)
18753+{
2dfbb274 18754+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
4a4d8108
AM
18755+ return 0;
18756+ return inode_permission(h_inode, mask);
18757+}
1facf9fc 18758+
4a4d8108
AM
18759+int au_test_h_perm_sio(struct inode *h_inode, int mask)
18760+{
18761+ if (au_test_nfs(h_inode->i_sb)
18762+ && (mask & MAY_WRITE)
18763+ && S_ISDIR(h_inode->i_mode))
18764+ mask |= MAY_READ; /* force permission check */
18765+ return au_test_h_perm(h_inode, mask);
1facf9fc 18766+}
7f207e10 18767diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
eca34b5c
AM
18768--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
18769+++ linux/fs/aufs/inode.h 2019-07-11 15:42:14.468904634 +0200
9f237c51 18770@@ -0,0 +1,698 @@
062440b3 18771+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 18772+/*
ba1aed25 18773+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
18774+ *
18775+ * This program, aufs is free software; you can redistribute it and/or modify
18776+ * it under the terms of the GNU General Public License as published by
18777+ * the Free Software Foundation; either version 2 of the License, or
18778+ * (at your option) any later version.
18779+ *
18780+ * This program is distributed in the hope that it will be useful,
18781+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18782+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18783+ * GNU General Public License for more details.
18784+ *
18785+ * You should have received a copy of the GNU General Public License
523b37e3 18786+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18787+ */
1facf9fc 18788+
1308ab2a 18789+/*
4a4d8108 18790+ * inode operations
1308ab2a 18791+ */
dece6358 18792+
4a4d8108
AM
18793+#ifndef __AUFS_INODE_H__
18794+#define __AUFS_INODE_H__
dece6358 18795+
4a4d8108 18796+#ifdef __KERNEL__
1308ab2a 18797+
4a4d8108 18798+#include <linux/fsnotify.h>
4a4d8108 18799+#include "rwsem.h"
1308ab2a 18800+
4a4d8108 18801+struct vfsmount;
1facf9fc 18802+
4a4d8108
AM
18803+struct au_hnotify {
18804+#ifdef CONFIG_AUFS_HNOTIFY
18805+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 18806+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 18807+ struct fsnotify_mark hn_mark;
4a4d8108 18808+#endif
1c60b727 18809+ struct inode *hn_aufs_inode; /* no get/put */
9f237c51 18810+ struct rcu_head rcu;
4a4d8108
AM
18811+#endif
18812+} ____cacheline_aligned_in_smp;
1facf9fc 18813+
4a4d8108
AM
18814+struct au_hinode {
18815+ struct inode *hi_inode;
18816+ aufs_bindex_t hi_id;
18817+#ifdef CONFIG_AUFS_HNOTIFY
18818+ struct au_hnotify *hi_notify;
18819+#endif
dece6358 18820+
4a4d8108
AM
18821+ /* reference to the copied-up whiteout with get/put */
18822+ struct dentry *hi_whdentry;
18823+};
dece6358 18824+
537831f9
AM
18825+/* ig_flags */
18826+#define AuIG_HALF_REFRESHED 1
18827+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name)
18828+#define au_ig_fset(flags, name) \
18829+ do { (flags) |= AuIG_##name; } while (0)
18830+#define au_ig_fclr(flags, name) \
18831+ do { (flags) &= ~AuIG_##name; } while (0)
18832+
18833+struct au_iigen {
be52b249 18834+ spinlock_t ig_spin;
537831f9
AM
18835+ __u32 ig_generation, ig_flags;
18836+};
18837+
4a4d8108
AM
18838+struct au_vdir;
18839+struct au_iinfo {
7a9e40b8 18840+ struct au_iigen ii_generation;
4a4d8108 18841+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 18842+
4a4d8108 18843+ struct au_rwsem ii_rwsem;
5afbbe0d 18844+ aufs_bindex_t ii_btop, ii_bbot;
4a4d8108
AM
18845+ __u32 ii_higen;
18846+ struct au_hinode *ii_hinode;
18847+ struct au_vdir *ii_vdir;
18848+};
1facf9fc 18849+
4a4d8108 18850+struct au_icntnr {
9f237c51
AM
18851+ struct au_iinfo iinfo;
18852+ struct inode vfs_inode;
18853+ struct hlist_bl_node plink;
18854+ struct rcu_head rcu;
4a4d8108 18855+} ____cacheline_aligned_in_smp;
1308ab2a 18856+
4a4d8108
AM
18857+/* au_pin flags */
18858+#define AuPin_DI_LOCKED 1
18859+#define AuPin_MNT_WRITE (1 << 1)
18860+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
18861+#define au_fset_pin(flags, name) \
18862+ do { (flags) |= AuPin_##name; } while (0)
18863+#define au_fclr_pin(flags, name) \
18864+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
18865+
18866+struct au_pin {
18867+ /* input */
18868+ struct dentry *dentry;
18869+ unsigned int udba;
18870+ unsigned char lsc_di, lsc_hi, flags;
18871+ aufs_bindex_t bindex;
18872+
18873+ /* output */
18874+ struct dentry *parent;
18875+ struct au_hinode *hdir;
18876+ struct vfsmount *h_mnt;
86dc4139
AM
18877+
18878+ /* temporary unlock/relock for copyup */
18879+ struct dentry *h_dentry, *h_parent;
18880+ struct au_branch *br;
18881+ struct task_struct *task;
4a4d8108 18882+};
1facf9fc 18883+
86dc4139 18884+void au_pin_hdir_unlock(struct au_pin *p);
c1595e42 18885+int au_pin_hdir_lock(struct au_pin *p);
86dc4139 18886+int au_pin_hdir_relock(struct au_pin *p);
86dc4139
AM
18887+void au_pin_hdir_acquire_nest(struct au_pin *p);
18888+void au_pin_hdir_release(struct au_pin *p);
18889+
1308ab2a 18890+/* ---------------------------------------------------------------------- */
18891+
4a4d8108 18892+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 18893+{
5afbbe0d
AM
18894+ BUG_ON(is_bad_inode(inode));
18895+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
4a4d8108 18896+}
1facf9fc 18897+
4a4d8108 18898+/* ---------------------------------------------------------------------- */
1facf9fc 18899+
4a4d8108
AM
18900+/* inode.c */
18901+struct inode *au_igrab(struct inode *inode);
b95c5147 18902+void au_refresh_iop(struct inode *inode, int force_getattr);
027c5e7a 18903+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
18904+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
18905+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18906+ unsigned int d_type, ino_t *ino);
18907+struct inode *au_new_inode(struct dentry *dentry, int must_new);
18908+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18909+ struct inode *inode);
18910+int au_test_h_perm(struct inode *h_inode, int mask);
18911+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 18912+
4a4d8108
AM
18913+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
18914+ ino_t h_ino, unsigned int d_type, ino_t *ino)
18915+{
18916+#ifdef CONFIG_AUFS_SHWH
18917+ return au_ino(sb, bindex, h_ino, d_type, ino);
18918+#else
18919+ return 0;
18920+#endif
18921+}
1facf9fc 18922+
4a4d8108 18923+/* i_op.c */
b95c5147
AM
18924+enum {
18925+ AuIop_SYMLINK,
18926+ AuIop_DIR,
18927+ AuIop_OTHER,
18928+ AuIop_Last
18929+};
18930+extern struct inode_operations aufs_iop[AuIop_Last],
18931+ aufs_iop_nogetattr[AuIop_Last];
1308ab2a 18932+
4a4d8108
AM
18933+/* au_wr_dir flags */
18934+#define AuWrDir_ADD_ENTRY 1
7e9cd9fe
AM
18935+#define AuWrDir_ISDIR (1 << 1)
18936+#define AuWrDir_TMPFILE (1 << 2)
4a4d8108 18937+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
18938+#define au_fset_wrdir(flags, name) \
18939+ do { (flags) |= AuWrDir_##name; } while (0)
18940+#define au_fclr_wrdir(flags, name) \
18941+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 18942+
4a4d8108
AM
18943+struct au_wr_dir_args {
18944+ aufs_bindex_t force_btgt;
18945+ unsigned char flags;
18946+};
18947+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
18948+ struct au_wr_dir_args *args);
dece6358 18949+
4a4d8108
AM
18950+struct dentry *au_pinned_h_parent(struct au_pin *pin);
18951+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
18952+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
18953+ unsigned int udba, unsigned char flags);
18954+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
18955+ unsigned int udba, unsigned char flags) __must_check;
18956+int au_do_pin(struct au_pin *pin) __must_check;
18957+void au_unpin(struct au_pin *pin);
c1595e42
JR
18958+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen);
18959+
18960+#define AuIcpup_DID_CPUP 1
18961+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
18962+#define au_fset_icpup(flags, name) \
18963+ do { (flags) |= AuIcpup_##name; } while (0)
18964+#define au_fclr_icpup(flags, name) \
18965+ do { (flags) &= ~AuIcpup_##name; } while (0)
18966+
18967+struct au_icpup_args {
18968+ unsigned char flags;
18969+ unsigned char pin_flags;
18970+ aufs_bindex_t btgt;
18971+ unsigned int udba;
18972+ struct au_pin pin;
18973+ struct path h_path;
18974+ struct inode *h_inode;
18975+};
18976+
18977+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
18978+ struct au_icpup_args *a);
18979+
a2654f78
AM
18980+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
18981+ int locked);
1facf9fc 18982+
4a4d8108
AM
18983+/* i_op_add.c */
18984+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
18985+ struct dentry *h_parent, int isdir);
7eafdf33
AM
18986+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
18987+ dev_t dev);
4a4d8108 18988+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
7eafdf33 18989+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 18990+ bool want_excl);
b912730e
AM
18991+struct vfsub_aopen_args;
18992+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
18993+ struct vfsub_aopen_args *args);
38d290e6 18994+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode);
4a4d8108
AM
18995+int aufs_link(struct dentry *src_dentry, struct inode *dir,
18996+ struct dentry *dentry);
7eafdf33 18997+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
1facf9fc 18998+
4a4d8108
AM
18999+/* i_op_del.c */
19000+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
19001+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
19002+ struct dentry *h_parent, int isdir);
19003+int aufs_unlink(struct inode *dir, struct dentry *dentry);
19004+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 19005+
4a4d8108
AM
19006+/* i_op_ren.c */
19007+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
19008+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
f2c43d5f
AM
19009+ struct inode *dir, struct dentry *dentry,
19010+ unsigned int flags);
1facf9fc 19011+
4a4d8108
AM
19012+/* iinfo.c */
19013+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
19014+void au_hiput(struct au_hinode *hinode);
19015+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
19016+ struct dentry *h_wh);
19017+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 19018+
4a4d8108
AM
19019+/* hinode flags */
19020+#define AuHi_XINO 1
19021+#define AuHi_HNOTIFY (1 << 1)
19022+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
19023+#define au_fset_hi(flags, name) \
19024+ do { (flags) |= AuHi_##name; } while (0)
19025+#define au_fclr_hi(flags, name) \
19026+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 19027+
4a4d8108
AM
19028+#ifndef CONFIG_AUFS_HNOTIFY
19029+#undef AuHi_HNOTIFY
19030+#define AuHi_HNOTIFY 0
19031+#endif
1facf9fc 19032+
4a4d8108
AM
19033+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
19034+ struct inode *h_inode, unsigned int flags);
1facf9fc 19035+
537831f9 19036+void au_update_iigen(struct inode *inode, int half);
4a4d8108 19037+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 19038+
4a4d8108 19039+void au_icntnr_init_once(void *_c);
5afbbe0d 19040+void au_hinode_init(struct au_hinode *hinode);
4a4d8108
AM
19041+int au_iinfo_init(struct inode *inode);
19042+void au_iinfo_fin(struct inode *inode);
e2f27e51 19043+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink);
1308ab2a 19044+
e49829fe 19045+#ifdef CONFIG_PROC_FS
4a4d8108 19046+/* plink.c */
e49829fe 19047+int au_plink_maint(struct super_block *sb, int flags);
7e9cd9fe 19048+struct au_sbinfo;
e49829fe
JR
19049+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
19050+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
19051+#ifdef CONFIG_AUFS_DEBUG
19052+void au_plink_list(struct super_block *sb);
19053+#else
19054+AuStubVoid(au_plink_list, struct super_block *sb)
19055+#endif
19056+int au_plink_test(struct inode *inode);
19057+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
19058+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
19059+ struct dentry *h_dentry);
e49829fe
JR
19060+void au_plink_put(struct super_block *sb, int verbose);
19061+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 19062+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
19063+#else
19064+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
19065+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
19066+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
19067+AuStubVoid(au_plink_list, struct super_block *sb);
19068+AuStubInt0(au_plink_test, struct inode *inode);
19069+AuStub(struct dentry *, au_plink_lkup, return NULL,
19070+ struct inode *inode, aufs_bindex_t bindex);
19071+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
19072+ struct dentry *h_dentry);
19073+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
19074+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
19075+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
19076+#endif /* CONFIG_PROC_FS */
1facf9fc 19077+
c1595e42
JR
19078+#ifdef CONFIG_AUFS_XATTR
19079+/* xattr.c */
7e9cd9fe
AM
19080+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
19081+ unsigned int verbose);
c1595e42 19082+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size);
f2c43d5f 19083+void au_xattr_init(struct super_block *sb);
c1595e42
JR
19084+#else
19085+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src,
7e9cd9fe 19086+ int ignore_flags, unsigned int verbose);
f2c43d5f 19087+AuStubVoid(au_xattr_init, struct super_block *sb);
c1595e42
JR
19088+#endif
19089+
19090+#ifdef CONFIG_FS_POSIX_ACL
19091+struct posix_acl *aufs_get_acl(struct inode *inode, int type);
19092+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
19093+#endif
19094+
19095+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
19096+enum {
19097+ AU_XATTR_SET,
c1595e42
JR
19098+ AU_ACL_SET
19099+};
19100+
f2c43d5f 19101+struct au_sxattr {
c1595e42
JR
19102+ int type;
19103+ union {
19104+ struct {
19105+ const char *name;
19106+ const void *value;
19107+ size_t size;
19108+ int flags;
19109+ } set;
19110+ struct {
c1595e42
JR
19111+ struct posix_acl *acl;
19112+ int type;
19113+ } acl_set;
19114+ } u;
19115+};
f2c43d5f
AM
19116+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
19117+ struct au_sxattr *arg);
c1595e42
JR
19118+#endif
19119+
4a4d8108 19120+/* ---------------------------------------------------------------------- */
1308ab2a 19121+
4a4d8108
AM
19122+/* lock subclass for iinfo */
19123+enum {
19124+ AuLsc_II_CHILD, /* child first */
19125+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
19126+ AuLsc_II_CHILD3, /* copyup dirs */
19127+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
19128+ AuLsc_II_PARENT2,
19129+ AuLsc_II_PARENT3, /* copyup dirs */
19130+ AuLsc_II_NEW_CHILD
19131+};
1308ab2a 19132+
1facf9fc 19133+/*
4a4d8108
AM
19134+ * ii_read_lock_child, ii_write_lock_child,
19135+ * ii_read_lock_child2, ii_write_lock_child2,
19136+ * ii_read_lock_child3, ii_write_lock_child3,
19137+ * ii_read_lock_parent, ii_write_lock_parent,
19138+ * ii_read_lock_parent2, ii_write_lock_parent2,
19139+ * ii_read_lock_parent3, ii_write_lock_parent3,
19140+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 19141+ */
4a4d8108
AM
19142+#define AuReadLockFunc(name, lsc) \
19143+static inline void ii_read_lock_##name(struct inode *i) \
19144+{ \
19145+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
19146+}
19147+
19148+#define AuWriteLockFunc(name, lsc) \
19149+static inline void ii_write_lock_##name(struct inode *i) \
19150+{ \
19151+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
19152+}
19153+
19154+#define AuRWLockFuncs(name, lsc) \
19155+ AuReadLockFunc(name, lsc) \
19156+ AuWriteLockFunc(name, lsc)
19157+
19158+AuRWLockFuncs(child, CHILD);
19159+AuRWLockFuncs(child2, CHILD2);
19160+AuRWLockFuncs(child3, CHILD3);
19161+AuRWLockFuncs(parent, PARENT);
19162+AuRWLockFuncs(parent2, PARENT2);
19163+AuRWLockFuncs(parent3, PARENT3);
19164+AuRWLockFuncs(new_child, NEW_CHILD);
19165+
19166+#undef AuReadLockFunc
19167+#undef AuWriteLockFunc
19168+#undef AuRWLockFuncs
1facf9fc 19169+
8b6a4947
AM
19170+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem)
19171+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem)
19172+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem)
1facf9fc 19173+
4a4d8108
AM
19174+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
19175+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
19176+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 19177+
4a4d8108 19178+/* ---------------------------------------------------------------------- */
1308ab2a 19179+
027c5e7a
AM
19180+static inline void au_icntnr_init(struct au_icntnr *c)
19181+{
19182+#ifdef CONFIG_AUFS_DEBUG
19183+ c->vfs_inode.i_mode = 0;
19184+#endif
19185+}
19186+
cfc41e69 19187+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags)
4a4d8108 19188+{
537831f9
AM
19189+ unsigned int gen;
19190+ struct au_iinfo *iinfo;
be52b249 19191+ struct au_iigen *iigen;
537831f9
AM
19192+
19193+ iinfo = au_ii(inode);
be52b249
AM
19194+ iigen = &iinfo->ii_generation;
19195+ spin_lock(&iigen->ig_spin);
cfc41e69
AM
19196+ if (igflags)
19197+ *igflags = iigen->ig_flags;
be52b249
AM
19198+ gen = iigen->ig_generation;
19199+ spin_unlock(&iigen->ig_spin);
537831f9
AM
19200+
19201+ return gen;
4a4d8108 19202+}
1308ab2a 19203+
4a4d8108
AM
19204+/* tiny test for inode number */
19205+/* tmpfs generation is too rough */
19206+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
19207+{
19208+ struct au_iinfo *iinfo;
1308ab2a 19209+
4a4d8108
AM
19210+ iinfo = au_ii(inode);
19211+ AuRwMustAnyLock(&iinfo->ii_rwsem);
19212+ return !(iinfo->ii_hsb1 == h_inode->i_sb
19213+ && iinfo->ii_higen == h_inode->i_generation);
19214+}
1308ab2a 19215+
4a4d8108
AM
19216+static inline void au_iigen_dec(struct inode *inode)
19217+{
537831f9 19218+ struct au_iinfo *iinfo;
be52b249 19219+ struct au_iigen *iigen;
537831f9
AM
19220+
19221+ iinfo = au_ii(inode);
be52b249
AM
19222+ iigen = &iinfo->ii_generation;
19223+ spin_lock(&iigen->ig_spin);
19224+ iigen->ig_generation--;
19225+ spin_unlock(&iigen->ig_spin);
027c5e7a
AM
19226+}
19227+
19228+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
19229+{
19230+ int err;
19231+
19232+ err = 0;
537831f9 19233+ if (unlikely(inode && au_iigen(inode, NULL) != sigen))
027c5e7a
AM
19234+ err = -EIO;
19235+
19236+ return err;
4a4d8108 19237+}
1308ab2a 19238+
4a4d8108 19239+/* ---------------------------------------------------------------------- */
1308ab2a 19240+
5afbbe0d
AM
19241+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo,
19242+ aufs_bindex_t bindex)
19243+{
19244+ return iinfo->ii_hinode + bindex;
19245+}
19246+
19247+static inline int au_is_bad_inode(struct inode *inode)
19248+{
19249+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0));
19250+}
19251+
4a4d8108
AM
19252+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
19253+ aufs_bindex_t bindex)
19254+{
19255+ IiMustAnyLock(inode);
5afbbe0d 19256+ return au_hinode(au_ii(inode), bindex)->hi_id;
4a4d8108 19257+}
1308ab2a 19258+
5afbbe0d 19259+static inline aufs_bindex_t au_ibtop(struct inode *inode)
4a4d8108
AM
19260+{
19261+ IiMustAnyLock(inode);
5afbbe0d 19262+ return au_ii(inode)->ii_btop;
4a4d8108 19263+}
1308ab2a 19264+
5afbbe0d 19265+static inline aufs_bindex_t au_ibbot(struct inode *inode)
4a4d8108
AM
19266+{
19267+ IiMustAnyLock(inode);
5afbbe0d 19268+ return au_ii(inode)->ii_bbot;
4a4d8108 19269+}
1308ab2a 19270+
4a4d8108
AM
19271+static inline struct au_vdir *au_ivdir(struct inode *inode)
19272+{
19273+ IiMustAnyLock(inode);
19274+ return au_ii(inode)->ii_vdir;
19275+}
1308ab2a 19276+
4a4d8108
AM
19277+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
19278+{
19279+ IiMustAnyLock(inode);
5afbbe0d 19280+ return au_hinode(au_ii(inode), bindex)->hi_whdentry;
4a4d8108 19281+}
1308ab2a 19282+
5afbbe0d 19283+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19284+{
4a4d8108 19285+ IiMustWriteLock(inode);
5afbbe0d 19286+ au_ii(inode)->ii_btop = bindex;
4a4d8108 19287+}
1308ab2a 19288+
5afbbe0d 19289+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex)
4a4d8108
AM
19290+{
19291+ IiMustWriteLock(inode);
5afbbe0d 19292+ au_ii(inode)->ii_bbot = bindex;
1308ab2a 19293+}
19294+
4a4d8108
AM
19295+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
19296+{
19297+ IiMustWriteLock(inode);
19298+ au_ii(inode)->ii_vdir = vdir;
19299+}
1facf9fc 19300+
4a4d8108 19301+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19302+{
4a4d8108 19303+ IiMustAnyLock(inode);
5afbbe0d 19304+ return au_hinode(au_ii(inode), bindex);
4a4d8108 19305+}
dece6358 19306+
4a4d8108 19307+/* ---------------------------------------------------------------------- */
1facf9fc 19308+
4a4d8108
AM
19309+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
19310+{
19311+ if (pin)
19312+ return pin->parent;
19313+ return NULL;
1facf9fc 19314+}
19315+
4a4d8108 19316+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 19317+{
4a4d8108
AM
19318+ if (pin && pin->hdir)
19319+ return pin->hdir->hi_inode;
19320+ return NULL;
1308ab2a 19321+}
1facf9fc 19322+
4a4d8108
AM
19323+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
19324+{
19325+ if (pin)
19326+ return pin->hdir;
19327+ return NULL;
19328+}
1facf9fc 19329+
4a4d8108 19330+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 19331+{
4a4d8108
AM
19332+ if (pin)
19333+ pin->dentry = dentry;
19334+}
1308ab2a 19335+
4a4d8108
AM
19336+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
19337+ unsigned char lflag)
19338+{
19339+ if (pin) {
7f207e10 19340+ if (lflag)
4a4d8108 19341+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 19342+ else
4a4d8108 19343+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 19344+ }
4a4d8108
AM
19345+}
19346+
7e9cd9fe 19347+#if 0 /* reserved */
4a4d8108
AM
19348+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
19349+{
19350+ if (pin) {
19351+ dput(pin->parent);
19352+ pin->parent = dget(parent);
1facf9fc 19353+ }
4a4d8108 19354+}
7e9cd9fe 19355+#endif
1facf9fc 19356+
4a4d8108
AM
19357+/* ---------------------------------------------------------------------- */
19358+
027c5e7a 19359+struct au_branch;
4a4d8108
AM
19360+#ifdef CONFIG_AUFS_HNOTIFY
19361+struct au_hnotify_op {
19362+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 19363+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
19364+
19365+ /*
19366+ * if it returns true, the the caller should free hinode->hi_notify,
19367+ * otherwise ->free() frees it.
19368+ */
19369+ int (*free)(struct au_hinode *hinode,
19370+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
19371+
19372+ void (*fin)(void);
19373+ int (*init)(void);
027c5e7a
AM
19374+
19375+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
19376+ void (*fin_br)(struct au_branch *br);
19377+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
19378+};
19379+
19380+/* hnotify.c */
027c5e7a 19381+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
19382+void au_hn_free(struct au_hinode *hinode);
19383+void au_hn_ctl(struct au_hinode *hinode, int do_set);
19384+void au_hn_reset(struct inode *inode, unsigned int flags);
19385+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
fbc438ed 19386+ const struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
19387+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
19388+int au_hnotify_init_br(struct au_branch *br, int perm);
19389+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
19390+int __init au_hnotify_init(void);
19391+void au_hnotify_fin(void);
19392+
7f207e10 19393+/* hfsnotify.c */
4a4d8108
AM
19394+extern const struct au_hnotify_op au_hnotify_op;
19395+
19396+static inline
19397+void au_hn_init(struct au_hinode *hinode)
19398+{
19399+ hinode->hi_notify = NULL;
1308ab2a 19400+}
19401+
53392da6
AM
19402+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
19403+{
19404+ return hinode->hi_notify;
19405+}
19406+
4a4d8108 19407+#else
c1595e42
JR
19408+AuStub(int, au_hn_alloc, return -EOPNOTSUPP,
19409+ struct au_hinode *hinode __maybe_unused,
19410+ struct inode *inode __maybe_unused)
19411+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode)
4a4d8108
AM
19412+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
19413+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
19414+ int do_set __maybe_unused)
19415+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
19416+ unsigned int flags __maybe_unused)
027c5e7a
AM
19417+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
19418+ struct au_branch *br __maybe_unused,
19419+ int perm __maybe_unused)
19420+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
19421+ int perm __maybe_unused)
19422+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
19423+AuStubInt0(__init au_hnotify_init, void)
19424+AuStubVoid(au_hnotify_fin, void)
19425+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
19426+#endif /* CONFIG_AUFS_HNOTIFY */
19427+
19428+static inline void au_hn_suspend(struct au_hinode *hdir)
19429+{
19430+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 19431+}
19432+
4a4d8108 19433+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 19434+{
4a4d8108
AM
19435+ au_hn_ctl(hdir, /*do_set*/1);
19436+}
1308ab2a 19437+
5afbbe0d 19438+static inline void au_hn_inode_lock(struct au_hinode *hdir)
4a4d8108 19439+{
febd17d6 19440+ inode_lock(hdir->hi_inode);
4a4d8108
AM
19441+ au_hn_suspend(hdir);
19442+}
dece6358 19443+
5afbbe0d 19444+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir,
4a4d8108
AM
19445+ unsigned int sc __maybe_unused)
19446+{
febd17d6 19447+ inode_lock_nested(hdir->hi_inode, sc);
4a4d8108 19448+ au_hn_suspend(hdir);
1facf9fc 19449+}
1facf9fc 19450+
8b6a4947
AM
19451+#if 0 /* unused */
19452+#include "vfsub.h"
3c1bdaff
AM
19453+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir,
19454+ unsigned int sc)
19455+{
be118d29 19456+ inode_lock_shared_nested(hdir->hi_inode, sc);
3c1bdaff
AM
19457+ au_hn_suspend(hdir);
19458+}
8b6a4947 19459+#endif
3c1bdaff 19460+
5afbbe0d 19461+static inline void au_hn_inode_unlock(struct au_hinode *hdir)
4a4d8108
AM
19462+{
19463+ au_hn_resume(hdir);
febd17d6 19464+ inode_unlock(hdir->hi_inode);
4a4d8108
AM
19465+}
19466+
19467+#endif /* __KERNEL__ */
19468+#endif /* __AUFS_INODE_H__ */
7f207e10 19469diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
eca34b5c
AM
19470--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
19471+++ linux/fs/aufs/ioctl.c 2019-07-11 15:42:14.468904634 +0200
062440b3 19472@@ -0,0 +1,220 @@
cd7a4cd9 19473+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19474+/*
ba1aed25 19475+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
19476+ *
19477+ * This program, aufs is free software; you can redistribute it and/or modify
19478+ * it under the terms of the GNU General Public License as published by
19479+ * the Free Software Foundation; either version 2 of the License, or
19480+ * (at your option) any later version.
19481+ *
19482+ * This program is distributed in the hope that it will be useful,
19483+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19484+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19485+ * GNU General Public License for more details.
19486+ *
19487+ * You should have received a copy of the GNU General Public License
523b37e3 19488+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19489+ */
19490+
19491+/*
19492+ * ioctl
19493+ * plink-management and readdir in userspace.
19494+ * assist the pathconf(3) wrapper library.
c2b27bf2 19495+ * move-down
076b876e 19496+ * File-based Hierarchical Storage Management.
4a4d8108
AM
19497+ */
19498+
c2b27bf2
AM
19499+#include <linux/compat.h>
19500+#include <linux/file.h>
4a4d8108
AM
19501+#include "aufs.h"
19502+
1e00d052 19503+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
19504+{
19505+ int err, fd;
5afbbe0d 19506+ aufs_bindex_t wbi, bindex, bbot;
4a4d8108
AM
19507+ struct file *h_file;
19508+ struct super_block *sb;
19509+ struct dentry *root;
1e00d052
AM
19510+ struct au_branch *br;
19511+ struct aufs_wbr_fd wbrfd = {
19512+ .oflags = au_dir_roflags,
19513+ .brid = -1
19514+ };
19515+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
19516+ | O_NOATIME | O_CLOEXEC;
4a4d8108 19517+
1e00d052
AM
19518+ AuDebugOn(wbrfd.oflags & ~valid);
19519+
19520+ if (arg) {
19521+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
19522+ if (unlikely(err)) {
19523+ err = -EFAULT;
19524+ goto out;
19525+ }
19526+
19527+ err = -EINVAL;
19528+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
19529+ wbrfd.oflags |= au_dir_roflags;
19530+ AuDbg("0%o\n", wbrfd.oflags);
19531+ if (unlikely(wbrfd.oflags & ~valid))
19532+ goto out;
19533+ }
19534+
2000de60 19535+ fd = get_unused_fd_flags(0);
1e00d052
AM
19536+ err = fd;
19537+ if (unlikely(fd < 0))
4a4d8108 19538+ goto out;
4a4d8108 19539+
1e00d052 19540+ h_file = ERR_PTR(-EINVAL);
4a4d8108 19541+ wbi = 0;
1e00d052 19542+ br = NULL;
4a4d8108
AM
19543+ sb = path->dentry->d_sb;
19544+ root = sb->s_root;
19545+ aufs_read_lock(root, AuLock_IR);
5afbbe0d 19546+ bbot = au_sbbot(sb);
1e00d052
AM
19547+ if (wbrfd.brid >= 0) {
19548+ wbi = au_br_index(sb, wbrfd.brid);
5afbbe0d 19549+ if (unlikely(wbi < 0 || wbi > bbot))
1e00d052
AM
19550+ goto out_unlock;
19551+ }
19552+
19553+ h_file = ERR_PTR(-ENOENT);
19554+ br = au_sbr(sb, wbi);
19555+ if (!au_br_writable(br->br_perm)) {
19556+ if (arg)
19557+ goto out_unlock;
19558+
19559+ bindex = wbi + 1;
19560+ wbi = -1;
5afbbe0d 19561+ for (; bindex <= bbot; bindex++) {
1e00d052
AM
19562+ br = au_sbr(sb, bindex);
19563+ if (au_br_writable(br->br_perm)) {
4a4d8108 19564+ wbi = bindex;
1e00d052 19565+ br = au_sbr(sb, wbi);
4a4d8108
AM
19566+ break;
19567+ }
19568+ }
4a4d8108
AM
19569+ }
19570+ AuDbg("wbi %d\n", wbi);
1e00d052 19571+ if (wbi >= 0)
392086de
AM
19572+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL,
19573+ /*force_wr*/0);
1e00d052
AM
19574+
19575+out_unlock:
4a4d8108
AM
19576+ aufs_read_unlock(root, AuLock_IR);
19577+ err = PTR_ERR(h_file);
19578+ if (IS_ERR(h_file))
19579+ goto out_fd;
19580+
acd2b654 19581+ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */
4a4d8108
AM
19582+ fd_install(fd, h_file);
19583+ err = fd;
19584+ goto out; /* success */
19585+
4f0767ce 19586+out_fd:
4a4d8108 19587+ put_unused_fd(fd);
4f0767ce 19588+out:
1e00d052 19589+ AuTraceErr(err);
4a4d8108
AM
19590+ return err;
19591+}
19592+
19593+/* ---------------------------------------------------------------------- */
19594+
19595+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
19596+{
19597+ long err;
c1595e42 19598+ struct dentry *dentry;
4a4d8108
AM
19599+
19600+ switch (cmd) {
4a4d8108
AM
19601+ case AUFS_CTL_RDU:
19602+ case AUFS_CTL_RDU_INO:
19603+ err = au_rdu_ioctl(file, cmd, arg);
19604+ break;
19605+
19606+ case AUFS_CTL_WBR_FD:
1e00d052 19607+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19608+ break;
19609+
027c5e7a
AM
19610+ case AUFS_CTL_IBUSY:
19611+ err = au_ibusy_ioctl(file, arg);
19612+ break;
19613+
076b876e
AM
19614+ case AUFS_CTL_BRINFO:
19615+ err = au_brinfo_ioctl(file, arg);
19616+ break;
19617+
19618+ case AUFS_CTL_FHSM_FD:
2000de60 19619+ dentry = file->f_path.dentry;
c1595e42
JR
19620+ if (IS_ROOT(dentry))
19621+ err = au_fhsm_fd(dentry->d_sb, arg);
19622+ else
19623+ err = -ENOTTY;
076b876e
AM
19624+ break;
19625+
4a4d8108
AM
19626+ default:
19627+ /* do not call the lower */
19628+ AuDbg("0x%x\n", cmd);
19629+ err = -ENOTTY;
19630+ }
19631+
19632+ AuTraceErr(err);
19633+ return err;
19634+}
19635+
19636+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
19637+{
19638+ long err;
19639+
19640+ switch (cmd) {
c2b27bf2 19641+ case AUFS_CTL_MVDOWN:
2000de60 19642+ err = au_mvdown(file->f_path.dentry, (void __user *)arg);
c2b27bf2
AM
19643+ break;
19644+
4a4d8108 19645+ case AUFS_CTL_WBR_FD:
1e00d052 19646+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19647+ break;
19648+
19649+ default:
19650+ /* do not call the lower */
19651+ AuDbg("0x%x\n", cmd);
19652+ err = -ENOTTY;
19653+ }
19654+
19655+ AuTraceErr(err);
19656+ return err;
19657+}
b752ccd1
AM
19658+
19659+#ifdef CONFIG_COMPAT
19660+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
19661+ unsigned long arg)
19662+{
19663+ long err;
19664+
19665+ switch (cmd) {
19666+ case AUFS_CTL_RDU:
19667+ case AUFS_CTL_RDU_INO:
19668+ err = au_rdu_compat_ioctl(file, cmd, arg);
19669+ break;
19670+
027c5e7a
AM
19671+ case AUFS_CTL_IBUSY:
19672+ err = au_ibusy_compat_ioctl(file, arg);
19673+ break;
19674+
076b876e
AM
19675+ case AUFS_CTL_BRINFO:
19676+ err = au_brinfo_compat_ioctl(file, arg);
19677+ break;
19678+
b752ccd1
AM
19679+ default:
19680+ err = aufs_ioctl_dir(file, cmd, arg);
19681+ }
19682+
19683+ AuTraceErr(err);
19684+ return err;
19685+}
19686+
b752ccd1
AM
19687+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
19688+ unsigned long arg)
19689+{
19690+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
19691+}
19692+#endif
7f207e10 19693diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
eca34b5c
AM
19694--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
19695+++ linux/fs/aufs/i_op_add.c 2019-07-11 15:42:14.468904634 +0200
eca801bf 19696@@ -0,0 +1,936 @@
cd7a4cd9 19697+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19698+/*
ba1aed25 19699+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
19700+ *
19701+ * This program, aufs is free software; you can redistribute it and/or modify
19702+ * it under the terms of the GNU General Public License as published by
19703+ * the Free Software Foundation; either version 2 of the License, or
19704+ * (at your option) any later version.
19705+ *
19706+ * This program is distributed in the hope that it will be useful,
19707+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19708+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19709+ * GNU General Public License for more details.
19710+ *
19711+ * You should have received a copy of the GNU General Public License
523b37e3 19712+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19713+ */
19714+
19715+/*
19716+ * inode operations (add entry)
19717+ */
19718+
eca801bf 19719+#include <linux/iversion.h>
4a4d8108
AM
19720+#include "aufs.h"
19721+
19722+/*
19723+ * final procedure of adding a new entry, except link(2).
19724+ * remove whiteout, instantiate, copyup the parent dir's times and size
19725+ * and update version.
19726+ * if it failed, re-create the removed whiteout.
19727+ */
19728+static int epilog(struct inode *dir, aufs_bindex_t bindex,
19729+ struct dentry *wh_dentry, struct dentry *dentry)
19730+{
19731+ int err, rerr;
19732+ aufs_bindex_t bwh;
19733+ struct path h_path;
076b876e 19734+ struct super_block *sb;
4a4d8108
AM
19735+ struct inode *inode, *h_dir;
19736+ struct dentry *wh;
19737+
19738+ bwh = -1;
076b876e 19739+ sb = dir->i_sb;
4a4d8108 19740+ if (wh_dentry) {
5527c038 19741+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
4a4d8108
AM
19742+ IMustLock(h_dir);
19743+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
19744+ bwh = au_dbwh(dentry);
19745+ h_path.dentry = wh_dentry;
076b876e 19746+ h_path.mnt = au_sbr_mnt(sb, bindex);
4a4d8108
AM
19747+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
19748+ dentry);
19749+ if (unlikely(err))
19750+ goto out;
19751+ }
19752+
19753+ inode = au_new_inode(dentry, /*must_new*/1);
19754+ if (!IS_ERR(inode)) {
19755+ d_instantiate(dentry, inode);
5527c038 19756+ dir = d_inode(dentry->d_parent); /* dir inode is locked */
4a4d8108 19757+ IMustLock(dir);
b912730e 19758+ au_dir_ts(dir, bindex);
be118d29 19759+ inode_inc_iversion(dir);
076b876e 19760+ au_fhsm_wrote(sb, bindex, /*force*/0);
4a4d8108
AM
19761+ return 0; /* success */
19762+ }
19763+
19764+ err = PTR_ERR(inode);
19765+ if (!wh_dentry)
19766+ goto out;
19767+
19768+ /* revert */
19769+ /* dir inode is locked */
19770+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
19771+ rerr = PTR_ERR(wh);
19772+ if (IS_ERR(wh)) {
523b37e3
AM
19773+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n",
19774+ dentry, err, rerr);
4a4d8108
AM
19775+ err = -EIO;
19776+ } else
19777+ dput(wh);
19778+
4f0767ce 19779+out:
4a4d8108
AM
19780+ return err;
19781+}
19782+
027c5e7a
AM
19783+static int au_d_may_add(struct dentry *dentry)
19784+{
19785+ int err;
19786+
19787+ err = 0;
19788+ if (unlikely(d_unhashed(dentry)))
19789+ err = -ENOENT;
5527c038 19790+ if (unlikely(d_really_is_positive(dentry)))
027c5e7a
AM
19791+ err = -EEXIST;
19792+ return err;
19793+}
19794+
4a4d8108
AM
19795+/*
19796+ * simple tests for the adding inode operations.
19797+ * following the checks in vfs, plus the parent-child relationship.
19798+ */
19799+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
19800+ struct dentry *h_parent, int isdir)
19801+{
19802+ int err;
19803+ umode_t h_mode;
19804+ struct dentry *h_dentry;
19805+ struct inode *h_inode;
19806+
19807+ err = -ENAMETOOLONG;
19808+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19809+ goto out;
19810+
19811+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 19812+ if (d_really_is_negative(dentry)) {
4a4d8108 19813+ err = -EEXIST;
5527c038 19814+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
19815+ goto out;
19816+ } else {
19817+ /* rename(2) case */
19818+ err = -EIO;
5527c038
JR
19819+ if (unlikely(d_is_negative(h_dentry)))
19820+ goto out;
19821+ h_inode = d_inode(h_dentry);
19822+ if (unlikely(!h_inode->i_nlink))
4a4d8108
AM
19823+ goto out;
19824+
19825+ h_mode = h_inode->i_mode;
19826+ if (!isdir) {
19827+ err = -EISDIR;
19828+ if (unlikely(S_ISDIR(h_mode)))
19829+ goto out;
19830+ } else if (unlikely(!S_ISDIR(h_mode))) {
19831+ err = -ENOTDIR;
19832+ goto out;
19833+ }
19834+ }
19835+
19836+ err = 0;
19837+ /* expected parent dir is locked */
19838+ if (unlikely(h_parent != h_dentry->d_parent))
19839+ err = -EIO;
19840+
4f0767ce 19841+out:
4a4d8108
AM
19842+ AuTraceErr(err);
19843+ return err;
19844+}
19845+
19846+/*
19847+ * initial procedure of adding a new entry.
19848+ * prepare writable branch and the parent dir, lock it,
19849+ * and lookup whiteout for the new entry.
19850+ */
19851+static struct dentry*
19852+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
19853+ struct dentry *src_dentry, struct au_pin *pin,
19854+ struct au_wr_dir_args *wr_dir_args)
19855+{
19856+ struct dentry *wh_dentry, *h_parent;
19857+ struct super_block *sb;
19858+ struct au_branch *br;
19859+ int err;
19860+ unsigned int udba;
19861+ aufs_bindex_t bcpup;
19862+
523b37e3 19863+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19864+
19865+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
19866+ bcpup = err;
19867+ wh_dentry = ERR_PTR(err);
19868+ if (unlikely(err < 0))
19869+ goto out;
19870+
19871+ sb = dentry->d_sb;
19872+ udba = au_opt_udba(sb);
19873+ err = au_pin(pin, dentry, bcpup, udba,
19874+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
19875+ wh_dentry = ERR_PTR(err);
19876+ if (unlikely(err))
19877+ goto out;
19878+
19879+ h_parent = au_pinned_h_parent(pin);
19880+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 19881+ && au_dbtop(dentry) == bcpup)
4a4d8108
AM
19882+ err = au_may_add(dentry, bcpup, h_parent,
19883+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
19884+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19885+ err = -ENAMETOOLONG;
19886+ wh_dentry = ERR_PTR(err);
19887+ if (unlikely(err))
19888+ goto out_unpin;
19889+
19890+ br = au_sbr(sb, bcpup);
19891+ if (dt) {
19892+ struct path tmp = {
19893+ .dentry = h_parent,
86dc4139 19894+ .mnt = au_br_mnt(br)
4a4d8108
AM
19895+ };
19896+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
19897+ }
19898+
19899+ wh_dentry = NULL;
19900+ if (bcpup != au_dbwh(dentry))
19901+ goto out; /* success */
19902+
2000de60
JR
19903+ /*
19904+ * ENAMETOOLONG here means that if we allowed create such name, then it
19905+ * would not be able to removed in the future. So we don't allow such
19906+ * name here and we don't handle ENAMETOOLONG differently here.
19907+ */
4a4d8108
AM
19908+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
19909+
4f0767ce 19910+out_unpin:
4a4d8108
AM
19911+ if (IS_ERR(wh_dentry))
19912+ au_unpin(pin);
4f0767ce 19913+out:
4a4d8108
AM
19914+ return wh_dentry;
19915+}
19916+
19917+/* ---------------------------------------------------------------------- */
19918+
19919+enum { Mknod, Symlink, Creat };
19920+struct simple_arg {
19921+ int type;
19922+ union {
19923+ struct {
b912730e
AM
19924+ umode_t mode;
19925+ bool want_excl;
19926+ bool try_aopen;
19927+ struct vfsub_aopen_args *aopen;
4a4d8108
AM
19928+ } c;
19929+ struct {
19930+ const char *symname;
19931+ } s;
19932+ struct {
7eafdf33 19933+ umode_t mode;
4a4d8108
AM
19934+ dev_t dev;
19935+ } m;
19936+ } u;
19937+};
19938+
19939+static int add_simple(struct inode *dir, struct dentry *dentry,
19940+ struct simple_arg *arg)
19941+{
076b876e 19942+ int err, rerr;
5afbbe0d 19943+ aufs_bindex_t btop;
4a4d8108 19944+ unsigned char created;
b912730e
AM
19945+ const unsigned char try_aopen
19946+ = (arg->type == Creat && arg->u.c.try_aopen);
acd2b654 19947+ struct vfsub_aopen_args *aopen = arg->u.c.aopen;
4a4d8108
AM
19948+ struct dentry *wh_dentry, *parent;
19949+ struct inode *h_dir;
b912730e
AM
19950+ struct super_block *sb;
19951+ struct au_branch *br;
acd2b654 19952+ /* to reduce stack size */
c2b27bf2
AM
19953+ struct {
19954+ struct au_dtime dt;
19955+ struct au_pin pin;
19956+ struct path h_path;
19957+ struct au_wr_dir_args wr_dir_args;
19958+ } *a;
4a4d8108 19959+
523b37e3 19960+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19961+ IMustLock(dir);
19962+
c2b27bf2
AM
19963+ err = -ENOMEM;
19964+ a = kmalloc(sizeof(*a), GFP_NOFS);
19965+ if (unlikely(!a))
19966+ goto out;
19967+ a->wr_dir_args.force_btgt = -1;
19968+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY;
19969+
4a4d8108 19970+ parent = dentry->d_parent; /* dir inode is locked */
b912730e
AM
19971+ if (!try_aopen) {
19972+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
19973+ if (unlikely(err))
19974+ goto out_free;
19975+ }
027c5e7a
AM
19976+ err = au_d_may_add(dentry);
19977+ if (unlikely(err))
19978+ goto out_unlock;
b912730e
AM
19979+ if (!try_aopen)
19980+ di_write_lock_parent(parent);
c2b27bf2
AM
19981+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
19982+ &a->pin, &a->wr_dir_args);
4a4d8108
AM
19983+ err = PTR_ERR(wh_dentry);
19984+ if (IS_ERR(wh_dentry))
027c5e7a 19985+ goto out_parent;
4a4d8108 19986+
5afbbe0d 19987+ btop = au_dbtop(dentry);
b912730e 19988+ sb = dentry->d_sb;
5afbbe0d
AM
19989+ br = au_sbr(sb, btop);
19990+ a->h_path.dentry = au_h_dptr(dentry, btop);
b912730e 19991+ a->h_path.mnt = au_br_mnt(br);
c2b27bf2 19992+ h_dir = au_pinned_h_dir(&a->pin);
4a4d8108
AM
19993+ switch (arg->type) {
19994+ case Creat:
acd2b654 19995+ if (!try_aopen || !h_dir->i_op->atomic_open) {
b912730e
AM
19996+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode,
19997+ arg->u.c.want_excl);
acd2b654
AM
19998+ created = !err;
19999+ if (!err && try_aopen)
20000+ aopen->file->f_mode |= FMODE_CREATED;
20001+ } else {
20002+ aopen->br = br;
20003+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen);
20004+ AuDbg("err %d\n", err);
20005+ AuDbgFile(aopen->file);
20006+ created = err >= 0
20007+ && !!(aopen->file->f_mode & FMODE_CREATED);
20008+ }
4a4d8108
AM
20009+ break;
20010+ case Symlink:
c2b27bf2 20011+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname);
acd2b654 20012+ created = !err;
4a4d8108
AM
20013+ break;
20014+ case Mknod:
c2b27bf2
AM
20015+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode,
20016+ arg->u.m.dev);
acd2b654 20017+ created = !err;
4a4d8108
AM
20018+ break;
20019+ default:
20020+ BUG();
20021+ }
acd2b654
AM
20022+ if (unlikely(err < 0))
20023+ goto out_unpin;
20024+
20025+ err = epilog(dir, btop, wh_dentry, dentry);
4a4d8108 20026+ if (!err)
acd2b654 20027+ goto out_unpin; /* success */
4a4d8108
AM
20028+
20029+ /* revert */
acd2b654 20030+ if (created /* && d_is_positive(a->h_path.dentry) */) {
523b37e3
AM
20031+ /* no delegation since it is just created */
20032+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL,
20033+ /*force*/0);
4a4d8108 20034+ if (rerr) {
523b37e3
AM
20035+ AuIOErr("%pd revert failure(%d, %d)\n",
20036+ dentry, err, rerr);
4a4d8108
AM
20037+ err = -EIO;
20038+ }
c2b27bf2 20039+ au_dtime_revert(&a->dt);
4a4d8108 20040+ }
acd2b654
AM
20041+ if (try_aopen && h_dir->i_op->atomic_open
20042+ && (aopen->file->f_mode & FMODE_OPENED))
20043+ /* aopen->file is still opened */
20044+ au_lcnt_dec(&aopen->br->br_nfiles);
4a4d8108 20045+
acd2b654 20046+out_unpin:
c2b27bf2 20047+ au_unpin(&a->pin);
4a4d8108 20048+ dput(wh_dentry);
027c5e7a 20049+out_parent:
b912730e
AM
20050+ if (!try_aopen)
20051+ di_write_unlock(parent);
027c5e7a 20052+out_unlock:
4a4d8108 20053+ if (unlikely(err)) {
5afbbe0d 20054+ au_update_dbtop(dentry);
4a4d8108
AM
20055+ d_drop(dentry);
20056+ }
b912730e
AM
20057+ if (!try_aopen)
20058+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 20059+out_free:
9f237c51 20060+ au_kfree_rcu(a);
027c5e7a 20061+out:
4a4d8108
AM
20062+ return err;
20063+}
20064+
7eafdf33
AM
20065+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
20066+ dev_t dev)
4a4d8108
AM
20067+{
20068+ struct simple_arg arg = {
20069+ .type = Mknod,
20070+ .u.m = {
20071+ .mode = mode,
20072+ .dev = dev
20073+ }
20074+ };
20075+ return add_simple(dir, dentry, &arg);
20076+}
20077+
20078+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
20079+{
20080+ struct simple_arg arg = {
20081+ .type = Symlink,
20082+ .u.s.symname = symname
20083+ };
20084+ return add_simple(dir, dentry, &arg);
20085+}
20086+
7eafdf33 20087+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 20088+ bool want_excl)
4a4d8108
AM
20089+{
20090+ struct simple_arg arg = {
20091+ .type = Creat,
20092+ .u.c = {
b4510431
AM
20093+ .mode = mode,
20094+ .want_excl = want_excl
4a4d8108
AM
20095+ }
20096+ };
20097+ return add_simple(dir, dentry, &arg);
20098+}
20099+
b912730e
AM
20100+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
20101+ struct vfsub_aopen_args *aopen_args)
20102+{
20103+ struct simple_arg arg = {
20104+ .type = Creat,
20105+ .u.c = {
20106+ .mode = aopen_args->create_mode,
20107+ .want_excl = aopen_args->open_flag & O_EXCL,
20108+ .try_aopen = true,
20109+ .aopen = aopen_args
20110+ }
20111+ };
20112+ return add_simple(dir, dentry, &arg);
20113+}
20114+
38d290e6
JR
20115+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
20116+{
20117+ int err;
20118+ aufs_bindex_t bindex;
20119+ struct super_block *sb;
20120+ struct dentry *parent, *h_parent, *h_dentry;
20121+ struct inode *h_dir, *inode;
20122+ struct vfsmount *h_mnt;
20123+ struct au_wr_dir_args wr_dir_args = {
20124+ .force_btgt = -1,
20125+ .flags = AuWrDir_TMPFILE
20126+ };
20127+
20128+ /* copy-up may happen */
febd17d6 20129+ inode_lock(dir);
38d290e6
JR
20130+
20131+ sb = dir->i_sb;
20132+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20133+ if (unlikely(err))
20134+ goto out;
20135+
20136+ err = au_di_init(dentry);
20137+ if (unlikely(err))
20138+ goto out_si;
20139+
20140+ err = -EBUSY;
20141+ parent = d_find_any_alias(dir);
20142+ AuDebugOn(!parent);
20143+ di_write_lock_parent(parent);
5527c038 20144+ if (unlikely(d_inode(parent) != dir))
38d290e6
JR
20145+ goto out_parent;
20146+
20147+ err = au_digen_test(parent, au_sigen(sb));
20148+ if (unlikely(err))
20149+ goto out_parent;
20150+
5afbbe0d
AM
20151+ bindex = au_dbtop(parent);
20152+ au_set_dbtop(dentry, bindex);
20153+ au_set_dbbot(dentry, bindex);
38d290e6
JR
20154+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
20155+ bindex = err;
20156+ if (unlikely(err < 0))
20157+ goto out_parent;
20158+
20159+ err = -EOPNOTSUPP;
20160+ h_dir = au_h_iptr(dir, bindex);
20161+ if (unlikely(!h_dir->i_op->tmpfile))
20162+ goto out_parent;
20163+
20164+ h_mnt = au_sbr_mnt(sb, bindex);
20165+ err = vfsub_mnt_want_write(h_mnt);
20166+ if (unlikely(err))
20167+ goto out_parent;
20168+
20169+ h_parent = au_h_dptr(parent, bindex);
521ced18
JR
20170+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0);
20171+ if (IS_ERR(h_dentry)) {
20172+ err = PTR_ERR(h_dentry);
38d290e6 20173+ goto out_mnt;
521ced18 20174+ }
38d290e6 20175+
5afbbe0d
AM
20176+ au_set_dbtop(dentry, bindex);
20177+ au_set_dbbot(dentry, bindex);
38d290e6
JR
20178+ au_set_h_dptr(dentry, bindex, dget(h_dentry));
20179+ inode = au_new_inode(dentry, /*must_new*/1);
20180+ if (IS_ERR(inode)) {
20181+ err = PTR_ERR(inode);
20182+ au_set_h_dptr(dentry, bindex, NULL);
5afbbe0d
AM
20183+ au_set_dbtop(dentry, -1);
20184+ au_set_dbbot(dentry, -1);
38d290e6
JR
20185+ } else {
20186+ if (!inode->i_nlink)
20187+ set_nlink(inode, 1);
20188+ d_tmpfile(dentry, inode);
20189+ au_di(dentry)->di_tmpfile = 1;
20190+
20191+ /* update without i_mutex */
5afbbe0d 20192+ if (au_ibtop(dir) == au_dbtop(dentry))
38d290e6
JR
20193+ au_cpup_attr_timesizes(dir);
20194+ }
38d290e6 20195+ dput(h_dentry);
521ced18 20196+
38d290e6
JR
20197+out_mnt:
20198+ vfsub_mnt_drop_write(h_mnt);
20199+out_parent:
20200+ di_write_unlock(parent);
20201+ dput(parent);
20202+ di_write_unlock(dentry);
5afbbe0d 20203+ if (unlikely(err)) {
38d290e6
JR
20204+ au_di_fin(dentry);
20205+ dentry->d_fsdata = NULL;
20206+ }
20207+out_si:
20208+ si_read_unlock(sb);
20209+out:
febd17d6 20210+ inode_unlock(dir);
38d290e6
JR
20211+ return err;
20212+}
20213+
4a4d8108
AM
20214+/* ---------------------------------------------------------------------- */
20215+
20216+struct au_link_args {
20217+ aufs_bindex_t bdst, bsrc;
20218+ struct au_pin pin;
20219+ struct path h_path;
20220+ struct dentry *src_parent, *parent;
20221+};
20222+
20223+static int au_cpup_before_link(struct dentry *src_dentry,
20224+ struct au_link_args *a)
20225+{
20226+ int err;
20227+ struct dentry *h_src_dentry;
c2b27bf2
AM
20228+ struct au_cp_generic cpg = {
20229+ .dentry = src_dentry,
20230+ .bdst = a->bdst,
20231+ .bsrc = a->bsrc,
20232+ .len = -1,
20233+ .pin = &a->pin,
20234+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */
20235+ };
4a4d8108
AM
20236+
20237+ di_read_lock_parent(a->src_parent, AuLock_IR);
20238+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
20239+ if (unlikely(err))
20240+ goto out;
20241+
20242+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
4a4d8108
AM
20243+ err = au_pin(&a->pin, src_dentry, a->bdst,
20244+ au_opt_udba(src_dentry->d_sb),
20245+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20246+ if (unlikely(err))
20247+ goto out;
367653fa 20248+
c2b27bf2 20249+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
20250+ au_unpin(&a->pin);
20251+
4f0767ce 20252+out:
4a4d8108
AM
20253+ di_read_unlock(a->src_parent, AuLock_IR);
20254+ return err;
20255+}
20256+
86dc4139
AM
20257+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
20258+ struct au_link_args *a)
4a4d8108
AM
20259+{
20260+ int err;
20261+ unsigned char plink;
5afbbe0d 20262+ aufs_bindex_t bbot;
4a4d8108 20263+ struct dentry *h_src_dentry;
523b37e3 20264+ struct inode *h_inode, *inode, *delegated;
4a4d8108
AM
20265+ struct super_block *sb;
20266+ struct file *h_file;
20267+
20268+ plink = 0;
20269+ h_inode = NULL;
20270+ sb = src_dentry->d_sb;
5527c038 20271+ inode = d_inode(src_dentry);
5afbbe0d 20272+ if (au_ibtop(inode) <= a->bdst)
4a4d8108
AM
20273+ h_inode = au_h_iptr(inode, a->bdst);
20274+ if (!h_inode || !h_inode->i_nlink) {
20275+ /* copyup src_dentry as the name of dentry. */
5afbbe0d
AM
20276+ bbot = au_dbbot(dentry);
20277+ if (bbot < a->bsrc)
20278+ au_set_dbbot(dentry, a->bsrc);
86dc4139
AM
20279+ au_set_h_dptr(dentry, a->bsrc,
20280+ dget(au_h_dptr(src_dentry, a->bsrc)));
20281+ dget(a->h_path.dentry);
20282+ au_set_h_dptr(dentry, a->bdst, NULL);
c1595e42
JR
20283+ AuDbg("temporary d_inode...\n");
20284+ spin_lock(&dentry->d_lock);
5527c038 20285+ dentry->d_inode = d_inode(src_dentry); /* tmp */
c1595e42 20286+ spin_unlock(&dentry->d_lock);
392086de 20287+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0);
86dc4139 20288+ if (IS_ERR(h_file))
4a4d8108 20289+ err = PTR_ERR(h_file);
86dc4139 20290+ else {
c2b27bf2
AM
20291+ struct au_cp_generic cpg = {
20292+ .dentry = dentry,
20293+ .bdst = a->bdst,
20294+ .bsrc = -1,
20295+ .len = -1,
20296+ .pin = &a->pin,
20297+ .flags = AuCpup_KEEPLINO
20298+ };
20299+ err = au_sio_cpup_simple(&cpg);
86dc4139
AM
20300+ au_h_open_post(dentry, a->bsrc, h_file);
20301+ if (!err) {
20302+ dput(a->h_path.dentry);
20303+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20304+ } else
20305+ au_set_h_dptr(dentry, a->bdst,
20306+ a->h_path.dentry);
20307+ }
c1595e42 20308+ spin_lock(&dentry->d_lock);
86dc4139 20309+ dentry->d_inode = NULL; /* restore */
c1595e42
JR
20310+ spin_unlock(&dentry->d_lock);
20311+ AuDbg("temporary d_inode...done\n");
86dc4139 20312+ au_set_h_dptr(dentry, a->bsrc, NULL);
5afbbe0d 20313+ au_set_dbbot(dentry, bbot);
4a4d8108
AM
20314+ } else {
20315+ /* the inode of src_dentry already exists on a.bdst branch */
20316+ h_src_dentry = d_find_alias(h_inode);
20317+ if (!h_src_dentry && au_plink_test(inode)) {
20318+ plink = 1;
20319+ h_src_dentry = au_plink_lkup(inode, a->bdst);
20320+ err = PTR_ERR(h_src_dentry);
20321+ if (IS_ERR(h_src_dentry))
20322+ goto out;
20323+
5527c038 20324+ if (unlikely(d_is_negative(h_src_dentry))) {
4a4d8108
AM
20325+ dput(h_src_dentry);
20326+ h_src_dentry = NULL;
20327+ }
20328+
20329+ }
20330+ if (h_src_dentry) {
523b37e3 20331+ delegated = NULL;
4a4d8108 20332+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20333+ &a->h_path, &delegated);
20334+ if (unlikely(err == -EWOULDBLOCK)) {
20335+ pr_warn("cannot retry for NFSv4 delegation"
20336+ " for an internal link\n");
20337+ iput(delegated);
20338+ }
4a4d8108
AM
20339+ dput(h_src_dentry);
20340+ } else {
20341+ AuIOErr("no dentry found for hi%lu on b%d\n",
20342+ h_inode->i_ino, a->bdst);
20343+ err = -EIO;
20344+ }
20345+ }
20346+
20347+ if (!err && !plink)
20348+ au_plink_append(inode, a->bdst, a->h_path.dentry);
20349+
20350+out:
2cbb1c4b 20351+ AuTraceErr(err);
4a4d8108
AM
20352+ return err;
20353+}
20354+
20355+int aufs_link(struct dentry *src_dentry, struct inode *dir,
20356+ struct dentry *dentry)
20357+{
20358+ int err, rerr;
20359+ struct au_dtime dt;
20360+ struct au_link_args *a;
20361+ struct dentry *wh_dentry, *h_src_dentry;
523b37e3 20362+ struct inode *inode, *delegated;
4a4d8108
AM
20363+ struct super_block *sb;
20364+ struct au_wr_dir_args wr_dir_args = {
20365+ /* .force_btgt = -1, */
20366+ .flags = AuWrDir_ADD_ENTRY
20367+ };
20368+
20369+ IMustLock(dir);
5527c038 20370+ inode = d_inode(src_dentry);
4a4d8108
AM
20371+ IMustLock(inode);
20372+
4a4d8108
AM
20373+ err = -ENOMEM;
20374+ a = kzalloc(sizeof(*a), GFP_NOFS);
20375+ if (unlikely(!a))
20376+ goto out;
20377+
20378+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
20379+ err = aufs_read_and_write_lock2(dentry, src_dentry,
20380+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
20381+ if (unlikely(err))
20382+ goto out_kfree;
38d290e6 20383+ err = au_d_linkable(src_dentry);
027c5e7a
AM
20384+ if (unlikely(err))
20385+ goto out_unlock;
20386+ err = au_d_may_add(dentry);
20387+ if (unlikely(err))
20388+ goto out_unlock;
e49829fe 20389+
4a4d8108 20390+ a->src_parent = dget_parent(src_dentry);
5afbbe0d 20391+ wr_dir_args.force_btgt = au_ibtop(inode);
4a4d8108
AM
20392+
20393+ di_write_lock_parent(a->parent);
20394+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
20395+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
20396+ &wr_dir_args);
20397+ err = PTR_ERR(wh_dentry);
20398+ if (IS_ERR(wh_dentry))
027c5e7a 20399+ goto out_parent;
4a4d8108
AM
20400+
20401+ err = 0;
20402+ sb = dentry->d_sb;
5afbbe0d 20403+ a->bdst = au_dbtop(dentry);
4a4d8108
AM
20404+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20405+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
5afbbe0d 20406+ a->bsrc = au_ibtop(inode);
2cbb1c4b 20407+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
38d290e6
JR
20408+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile)
20409+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc));
2cbb1c4b 20410+ if (!h_src_dentry) {
5afbbe0d 20411+ a->bsrc = au_dbtop(src_dentry);
2cbb1c4b
JR
20412+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
20413+ AuDebugOn(!h_src_dentry);
38d290e6
JR
20414+ } else if (IS_ERR(h_src_dentry)) {
20415+ err = PTR_ERR(h_src_dentry);
2cbb1c4b 20416+ goto out_parent;
38d290e6 20417+ }
2cbb1c4b 20418+
f2c43d5f
AM
20419+ /*
20420+ * aufs doesn't touch the credential so
acd2b654 20421+ * security_dentry_create_files_as() is unnecessary.
f2c43d5f 20422+ */
4a4d8108
AM
20423+ if (au_opt_test(au_mntflags(sb), PLINK)) {
20424+ if (a->bdst < a->bsrc
20425+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
86dc4139 20426+ err = au_cpup_or_link(src_dentry, dentry, a);
523b37e3
AM
20427+ else {
20428+ delegated = NULL;
4a4d8108 20429+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20430+ &a->h_path, &delegated);
20431+ if (unlikely(err == -EWOULDBLOCK)) {
20432+ pr_warn("cannot retry for NFSv4 delegation"
20433+ " for an internal link\n");
20434+ iput(delegated);
20435+ }
20436+ }
2cbb1c4b 20437+ dput(h_src_dentry);
4a4d8108
AM
20438+ } else {
20439+ /*
20440+ * copyup src_dentry to the branch we process,
20441+ * and then link(2) to it.
20442+ */
2cbb1c4b 20443+ dput(h_src_dentry);
4a4d8108
AM
20444+ if (a->bdst < a->bsrc
20445+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
20446+ au_unpin(&a->pin);
20447+ di_write_unlock(a->parent);
20448+ err = au_cpup_before_link(src_dentry, a);
20449+ di_write_lock_parent(a->parent);
20450+ if (!err)
20451+ err = au_pin(&a->pin, dentry, a->bdst,
20452+ au_opt_udba(sb),
20453+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20454+ if (unlikely(err))
20455+ goto out_wh;
20456+ }
20457+ if (!err) {
20458+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
20459+ err = -ENOENT;
5527c038 20460+ if (h_src_dentry && d_is_positive(h_src_dentry)) {
523b37e3 20461+ delegated = NULL;
4a4d8108
AM
20462+ err = vfsub_link(h_src_dentry,
20463+ au_pinned_h_dir(&a->pin),
523b37e3
AM
20464+ &a->h_path, &delegated);
20465+ if (unlikely(err == -EWOULDBLOCK)) {
20466+ pr_warn("cannot retry"
20467+ " for NFSv4 delegation"
20468+ " for an internal link\n");
20469+ iput(delegated);
20470+ }
20471+ }
4a4d8108
AM
20472+ }
20473+ }
20474+ if (unlikely(err))
20475+ goto out_unpin;
20476+
20477+ if (wh_dentry) {
20478+ a->h_path.dentry = wh_dentry;
20479+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
20480+ dentry);
20481+ if (unlikely(err))
20482+ goto out_revert;
20483+ }
20484+
b912730e 20485+ au_dir_ts(dir, a->bdst);
be118d29 20486+ inode_inc_iversion(dir);
4a4d8108
AM
20487+ inc_nlink(inode);
20488+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
20489+ d_instantiate(dentry, au_igrab(inode));
20490+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
20491+ /* some filesystem calls d_drop() */
20492+ d_drop(dentry);
076b876e
AM
20493+ /* some filesystems consume an inode even hardlink */
20494+ au_fhsm_wrote(sb, a->bdst, /*force*/0);
4a4d8108
AM
20495+ goto out_unpin; /* success */
20496+
4f0767ce 20497+out_revert:
523b37e3
AM
20498+ /* no delegation since it is just created */
20499+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path,
20500+ /*delegated*/NULL, /*force*/0);
027c5e7a 20501+ if (unlikely(rerr)) {
523b37e3 20502+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr);
027c5e7a
AM
20503+ err = -EIO;
20504+ }
4a4d8108 20505+ au_dtime_revert(&dt);
4f0767ce 20506+out_unpin:
4a4d8108 20507+ au_unpin(&a->pin);
4f0767ce 20508+out_wh:
4a4d8108 20509+ dput(wh_dentry);
027c5e7a
AM
20510+out_parent:
20511+ di_write_unlock(a->parent);
20512+ dput(a->src_parent);
4f0767ce 20513+out_unlock:
4a4d8108 20514+ if (unlikely(err)) {
5afbbe0d 20515+ au_update_dbtop(dentry);
4a4d8108
AM
20516+ d_drop(dentry);
20517+ }
4a4d8108 20518+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 20519+out_kfree:
9f237c51 20520+ au_kfree_rcu(a);
4f0767ce 20521+out:
86dc4139 20522+ AuTraceErr(err);
4a4d8108
AM
20523+ return err;
20524+}
20525+
7eafdf33 20526+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
20527+{
20528+ int err, rerr;
20529+ aufs_bindex_t bindex;
20530+ unsigned char diropq;
20531+ struct path h_path;
20532+ struct dentry *wh_dentry, *parent, *opq_dentry;
febd17d6 20533+ struct inode *h_inode;
4a4d8108
AM
20534+ struct super_block *sb;
20535+ struct {
20536+ struct au_pin pin;
20537+ struct au_dtime dt;
20538+ } *a; /* reduce the stack usage */
20539+ struct au_wr_dir_args wr_dir_args = {
20540+ .force_btgt = -1,
20541+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
20542+ };
20543+
20544+ IMustLock(dir);
20545+
20546+ err = -ENOMEM;
20547+ a = kmalloc(sizeof(*a), GFP_NOFS);
20548+ if (unlikely(!a))
20549+ goto out;
20550+
027c5e7a
AM
20551+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
20552+ if (unlikely(err))
20553+ goto out_free;
20554+ err = au_d_may_add(dentry);
20555+ if (unlikely(err))
20556+ goto out_unlock;
20557+
4a4d8108
AM
20558+ parent = dentry->d_parent; /* dir inode is locked */
20559+ di_write_lock_parent(parent);
20560+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
20561+ &a->pin, &wr_dir_args);
20562+ err = PTR_ERR(wh_dentry);
20563+ if (IS_ERR(wh_dentry))
027c5e7a 20564+ goto out_parent;
4a4d8108
AM
20565+
20566+ sb = dentry->d_sb;
5afbbe0d 20567+ bindex = au_dbtop(dentry);
4a4d8108
AM
20568+ h_path.dentry = au_h_dptr(dentry, bindex);
20569+ h_path.mnt = au_sbr_mnt(sb, bindex);
20570+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
20571+ if (unlikely(err))
027c5e7a 20572+ goto out_unpin;
4a4d8108
AM
20573+
20574+ /* make the dir opaque */
20575+ diropq = 0;
febd17d6 20576+ h_inode = d_inode(h_path.dentry);
4a4d8108
AM
20577+ if (wh_dentry
20578+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
febd17d6 20579+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20580+ opq_dentry = au_diropq_create(dentry, bindex);
febd17d6 20581+ inode_unlock(h_inode);
4a4d8108
AM
20582+ err = PTR_ERR(opq_dentry);
20583+ if (IS_ERR(opq_dentry))
20584+ goto out_dir;
20585+ dput(opq_dentry);
20586+ diropq = 1;
20587+ }
20588+
20589+ err = epilog(dir, bindex, wh_dentry, dentry);
20590+ if (!err) {
20591+ inc_nlink(dir);
027c5e7a 20592+ goto out_unpin; /* success */
4a4d8108
AM
20593+ }
20594+
20595+ /* revert */
20596+ if (diropq) {
20597+ AuLabel(revert opq);
febd17d6 20598+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20599+ rerr = au_diropq_remove(dentry, bindex);
febd17d6 20600+ inode_unlock(h_inode);
4a4d8108 20601+ if (rerr) {
523b37e3
AM
20602+ AuIOErr("%pd reverting diropq failed(%d, %d)\n",
20603+ dentry, err, rerr);
4a4d8108
AM
20604+ err = -EIO;
20605+ }
20606+ }
20607+
4f0767ce 20608+out_dir:
4a4d8108
AM
20609+ AuLabel(revert dir);
20610+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
20611+ if (rerr) {
523b37e3
AM
20612+ AuIOErr("%pd reverting dir failed(%d, %d)\n",
20613+ dentry, err, rerr);
4a4d8108
AM
20614+ err = -EIO;
20615+ }
4a4d8108 20616+ au_dtime_revert(&a->dt);
027c5e7a 20617+out_unpin:
4a4d8108
AM
20618+ au_unpin(&a->pin);
20619+ dput(wh_dentry);
027c5e7a
AM
20620+out_parent:
20621+ di_write_unlock(parent);
20622+out_unlock:
4a4d8108 20623+ if (unlikely(err)) {
5afbbe0d 20624+ au_update_dbtop(dentry);
4a4d8108
AM
20625+ d_drop(dentry);
20626+ }
4a4d8108 20627+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 20628+out_free:
9f237c51 20629+ au_kfree_rcu(a);
4f0767ce 20630+out:
4a4d8108
AM
20631+ return err;
20632+}
7f207e10 20633diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
eca34b5c
AM
20634--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
20635+++ linux/fs/aufs/i_op.c 2019-09-16 09:38:43.216175640 +0200
20636@@ -0,0 +1,1505 @@
cd7a4cd9 20637+// SPDX-License-Identifier: GPL-2.0
4a4d8108 20638+/*
ba1aed25 20639+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
20640+ *
20641+ * This program, aufs is free software; you can redistribute it and/or modify
20642+ * it under the terms of the GNU General Public License as published by
20643+ * the Free Software Foundation; either version 2 of the License, or
20644+ * (at your option) any later version.
20645+ *
20646+ * This program is distributed in the hope that it will be useful,
20647+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20648+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20649+ * GNU General Public License for more details.
20650+ *
20651+ * You should have received a copy of the GNU General Public License
523b37e3 20652+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 20653+ */
1facf9fc 20654+
1308ab2a 20655+/*
4a4d8108 20656+ * inode operations (except add/del/rename)
1308ab2a 20657+ */
4a4d8108
AM
20658+
20659+#include <linux/device_cgroup.h>
20660+#include <linux/fs_stack.h>
eca801bf 20661+#include <linux/iversion.h>
4a4d8108
AM
20662+#include <linux/namei.h>
20663+#include <linux/security.h>
4a4d8108
AM
20664+#include "aufs.h"
20665+
1e00d052 20666+static int h_permission(struct inode *h_inode, int mask,
79b8bda9 20667+ struct path *h_path, int brperm)
1facf9fc 20668+{
1308ab2a 20669+ int err;
4a4d8108 20670+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 20671+
e2f27e51
AM
20672+ err = -EPERM;
20673+ if (write_mask && IS_IMMUTABLE(h_inode))
20674+ goto out;
20675+
4a4d8108 20676+ err = -EACCES;
e2f27e51
AM
20677+ if (((mask & MAY_EXEC)
20678+ && S_ISREG(h_inode->i_mode)
20679+ && (path_noexec(h_path)
cd7a4cd9 20680+ || !(h_inode->i_mode & 0111))))
4a4d8108
AM
20681+ goto out;
20682+
20683+ /*
20684+ * - skip the lower fs test in the case of write to ro branch.
20685+ * - nfs dir permission write check is optimized, but a policy for
20686+ * link/rename requires a real check.
2121bcd9 20687+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e 20688+ * in this case, generic_permission() returns -EOPNOTSUPP.
4a4d8108
AM
20689+ */
20690+ if ((write_mask && !au_br_writable(brperm))
20691+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
20692+ && write_mask && !(mask & MAY_READ))
20693+ || !h_inode->i_op->permission) {
20694+ /* AuLabel(generic_permission); */
062440b3 20695+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */
1e00d052 20696+ err = generic_permission(h_inode, mask);
b912730e
AM
20697+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode))
20698+ err = h_inode->i_op->permission(h_inode, mask);
20699+ AuTraceErr(err);
1308ab2a 20700+ } else {
4a4d8108 20701+ /* AuLabel(h_inode->permission); */
1e00d052 20702+ err = h_inode->i_op->permission(h_inode, mask);
4a4d8108
AM
20703+ AuTraceErr(err);
20704+ }
1facf9fc 20705+
4a4d8108
AM
20706+ if (!err)
20707+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 20708+ if (!err)
4a4d8108 20709+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
20710+
20711+#if 0
20712+ if (!err) {
20713+ /* todo: do we need to call ima_path_check()? */
20714+ struct path h_path = {
20715+ .dentry =
20716+ .mnt = h_mnt
20717+ };
20718+ err = ima_path_check(&h_path,
20719+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
20720+ IMA_COUNT_LEAVE);
1308ab2a 20721+ }
4a4d8108 20722+#endif
dece6358 20723+
4f0767ce 20724+out:
1308ab2a 20725+ return err;
20726+}
dece6358 20727+
1e00d052 20728+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 20729+{
20730+ int err;
5afbbe0d 20731+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
20732+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
20733+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
20734+ struct inode *h_inode;
20735+ struct super_block *sb;
20736+ struct au_branch *br;
1facf9fc 20737+
027c5e7a 20738+ /* todo: support rcu-walk? */
1e00d052 20739+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
20740+ return -ECHILD;
20741+
4a4d8108
AM
20742+ sb = inode->i_sb;
20743+ si_read_lock(sb, AuLock_FLUSH);
20744+ ii_read_lock_child(inode);
027c5e7a
AM
20745+#if 0
20746+ err = au_iigen_test(inode, au_sigen(sb));
20747+ if (unlikely(err))
20748+ goto out;
20749+#endif
dece6358 20750+
076b876e
AM
20751+ if (!isdir
20752+ || write_mask
20753+ || au_opt_test(au_mntflags(sb), DIRPERM1)) {
4a4d8108 20754+ err = au_busy_or_stale();
5afbbe0d 20755+ h_inode = au_h_iptr(inode, au_ibtop(inode));
4a4d8108
AM
20756+ if (unlikely(!h_inode
20757+ || (h_inode->i_mode & S_IFMT)
20758+ != (inode->i_mode & S_IFMT)))
20759+ goto out;
1facf9fc 20760+
4a4d8108 20761+ err = 0;
5afbbe0d 20762+ bindex = au_ibtop(inode);
4a4d8108 20763+ br = au_sbr(sb, bindex);
79b8bda9 20764+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm);
4a4d8108
AM
20765+ if (write_mask
20766+ && !err
20767+ && !special_file(h_inode->i_mode)) {
20768+ /* test whether the upper writable branch exists */
20769+ err = -EROFS;
20770+ for (; bindex >= 0; bindex--)
20771+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
20772+ err = 0;
20773+ break;
20774+ }
20775+ }
20776+ goto out;
20777+ }
dece6358 20778+
4a4d8108 20779+ /* non-write to dir */
1308ab2a 20780+ err = 0;
5afbbe0d
AM
20781+ bbot = au_ibbot(inode);
20782+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
20783+ h_inode = au_h_iptr(inode, bindex);
20784+ if (h_inode) {
20785+ err = au_busy_or_stale();
20786+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
20787+ break;
20788+
20789+ br = au_sbr(sb, bindex);
79b8bda9 20790+ err = h_permission(h_inode, mask, &br->br_path,
4a4d8108
AM
20791+ br->br_perm);
20792+ }
20793+ }
1308ab2a 20794+
4f0767ce 20795+out:
4a4d8108
AM
20796+ ii_read_unlock(inode);
20797+ si_read_unlock(sb);
1308ab2a 20798+ return err;
20799+}
20800+
4a4d8108 20801+/* ---------------------------------------------------------------------- */
1facf9fc 20802+
4a4d8108 20803+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
b4510431 20804+ unsigned int flags)
4a4d8108
AM
20805+{
20806+ struct dentry *ret, *parent;
b752ccd1 20807+ struct inode *inode;
4a4d8108 20808+ struct super_block *sb;
1716fcea 20809+ int err, npositive;
dece6358 20810+
4a4d8108 20811+ IMustLock(dir);
1308ab2a 20812+
537831f9
AM
20813+ /* todo: support rcu-walk? */
20814+ ret = ERR_PTR(-ECHILD);
20815+ if (flags & LOOKUP_RCU)
20816+ goto out;
20817+
20818+ ret = ERR_PTR(-ENAMETOOLONG);
20819+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
20820+ goto out;
20821+
4a4d8108 20822+ sb = dir->i_sb;
7f207e10
AM
20823+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20824+ ret = ERR_PTR(err);
20825+ if (unlikely(err))
20826+ goto out;
20827+
4a4d8108
AM
20828+ err = au_di_init(dentry);
20829+ ret = ERR_PTR(err);
20830+ if (unlikely(err))
7f207e10 20831+ goto out_si;
1308ab2a 20832+
9dbd164d 20833+ inode = NULL;
027c5e7a 20834+ npositive = 0; /* suppress a warning */
4a4d8108
AM
20835+ parent = dentry->d_parent; /* dir inode is locked */
20836+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
20837+ err = au_alive_dir(parent);
20838+ if (!err)
20839+ err = au_digen_test(parent, au_sigen(sb));
20840+ if (!err) {
5afbbe0d
AM
20841+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */
20842+ npositive = au_lkup_dentry(dentry, au_dbtop(parent),
20843+ AuLkup_ALLOW_NEG);
027c5e7a
AM
20844+ err = npositive;
20845+ }
4a4d8108 20846+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
20847+ ret = ERR_PTR(err);
20848+ if (unlikely(err < 0))
20849+ goto out_unlock;
1308ab2a 20850+
4a4d8108 20851+ if (npositive) {
b752ccd1 20852+ inode = au_new_inode(dentry, /*must_new*/0);
c1595e42
JR
20853+ if (IS_ERR(inode)) {
20854+ ret = (void *)inode;
20855+ inode = NULL;
20856+ goto out_unlock;
20857+ }
9dbd164d 20858+ }
4a4d8108 20859+
c1595e42
JR
20860+ if (inode)
20861+ atomic_inc(&inode->i_count);
4a4d8108 20862+ ret = d_splice_alias(inode, dentry);
537831f9
AM
20863+#if 0
20864+ if (unlikely(d_need_lookup(dentry))) {
20865+ spin_lock(&dentry->d_lock);
20866+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
20867+ spin_unlock(&dentry->d_lock);
20868+ } else
20869+#endif
c1595e42 20870+ if (inode) {
2000de60 20871+ if (!IS_ERR(ret)) {
c1595e42 20872+ iput(inode);
2000de60
JR
20873+ if (ret && ret != dentry)
20874+ ii_write_unlock(inode);
20875+ } else {
c1595e42
JR
20876+ ii_write_unlock(inode);
20877+ iput(inode);
20878+ inode = NULL;
20879+ }
7f207e10 20880+ }
1facf9fc 20881+
4f0767ce 20882+out_unlock:
4a4d8108 20883+ di_write_unlock(dentry);
7f207e10 20884+out_si:
4a4d8108 20885+ si_read_unlock(sb);
7f207e10 20886+out:
4a4d8108
AM
20887+ return ret;
20888+}
1facf9fc 20889+
4a4d8108 20890+/* ---------------------------------------------------------------------- */
1facf9fc 20891+
acd2b654
AM
20892+/*
20893+ * very dirty and complicated aufs ->atomic_open().
20894+ * aufs_atomic_open()
20895+ * + au_aopen_or_create()
20896+ * + add_simple()
20897+ * + vfsub_atomic_open()
20898+ * + branch fs ->atomic_open()
20899+ * may call the actual 'open' for h_file
20900+ * + inc br_nfiles only if opened
20901+ * + au_aopen_no_open() or au_aopen_do_open()
20902+ *
20903+ * au_aopen_do_open()
20904+ * + finish_open()
20905+ * + au_do_aopen()
20906+ * + au_do_open() the body of all 'open'
20907+ * + au_do_open_nondir()
20908+ * set the passed h_file
20909+ *
20910+ * au_aopen_no_open()
20911+ * + finish_no_open()
20912+ */
20913+
b912730e 20914+struct aopen_node {
8b6a4947 20915+ struct hlist_bl_node hblist;
b912730e
AM
20916+ struct file *file, *h_file;
20917+};
20918+
20919+static int au_do_aopen(struct inode *inode, struct file *file)
20920+{
8b6a4947
AM
20921+ struct hlist_bl_head *aopen;
20922+ struct hlist_bl_node *pos;
b912730e
AM
20923+ struct aopen_node *node;
20924+ struct au_do_open_args args = {
8b6a4947
AM
20925+ .aopen = 1,
20926+ .open = au_do_open_nondir
b912730e
AM
20927+ };
20928+
20929+ aopen = &au_sbi(inode->i_sb)->si_aopen;
8b6a4947
AM
20930+ hlist_bl_lock(aopen);
20931+ hlist_bl_for_each_entry(node, pos, aopen, hblist)
b912730e
AM
20932+ if (node->file == file) {
20933+ args.h_file = node->h_file;
20934+ break;
20935+ }
8b6a4947 20936+ hlist_bl_unlock(aopen);
b912730e
AM
20937+ /* AuDebugOn(!args.h_file); */
20938+
20939+ return au_do_open(file, &args);
20940+}
20941+
acd2b654
AM
20942+static int au_aopen_do_open(struct file *file, struct dentry *dentry,
20943+ struct aopen_node *aopen_node)
20944+{
20945+ int err;
20946+ struct hlist_bl_head *aopen;
20947+
20948+ AuLabel(here);
20949+ aopen = &au_sbi(dentry->d_sb)->si_aopen;
20950+ au_hbl_add(&aopen_node->hblist, aopen);
20951+ err = finish_open(file, dentry, au_do_aopen);
20952+ au_hbl_del(&aopen_node->hblist, aopen);
20953+ /* AuDbgFile(file); */
20954+ AuDbg("%pd%s%s\n", dentry,
20955+ (file->f_mode & FMODE_CREATED) ? " created" : "",
20956+ (file->f_mode & FMODE_OPENED) ? " opened" : "");
20957+
20958+ AuTraceErr(err);
20959+ return err;
20960+}
20961+
20962+static int au_aopen_no_open(struct file *file, struct dentry *dentry)
20963+{
20964+ int err;
20965+
20966+ AuLabel(here);
20967+ dget(dentry);
20968+ err = finish_no_open(file, dentry);
20969+
20970+ AuTraceErr(err);
20971+ return err;
20972+}
20973+
b912730e
AM
20974+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
20975+ struct file *file, unsigned int open_flag,
acd2b654 20976+ umode_t create_mode)
b912730e 20977+{
acd2b654 20978+ int err, did_open;
5afbbe0d 20979+ unsigned int lkup_flags;
acd2b654
AM
20980+ aufs_bindex_t bindex;
20981+ struct super_block *sb;
f0c0a007 20982+ struct dentry *parent, *d;
b912730e
AM
20983+ struct vfsub_aopen_args args = {
20984+ .open_flag = open_flag,
acd2b654 20985+ .create_mode = create_mode
b912730e
AM
20986+ };
20987+ struct aopen_node aopen_node = {
20988+ .file = file
20989+ };
20990+
20991+ IMustLock(dir);
5afbbe0d 20992+ AuDbg("open_flag 0%o\n", open_flag);
b912730e
AM
20993+ AuDbgDentry(dentry);
20994+
20995+ err = 0;
20996+ if (!au_di(dentry)) {
5afbbe0d
AM
20997+ lkup_flags = LOOKUP_OPEN;
20998+ if (open_flag & O_CREAT)
20999+ lkup_flags |= LOOKUP_CREATE;
21000+ d = aufs_lookup(dir, dentry, lkup_flags);
b912730e
AM
21001+ if (IS_ERR(d)) {
21002+ err = PTR_ERR(d);
5afbbe0d 21003+ AuTraceErr(err);
b912730e
AM
21004+ goto out;
21005+ } else if (d) {
21006+ /*
21007+ * obsoleted dentry found.
21008+ * another error will be returned later.
21009+ */
21010+ d_drop(d);
b912730e 21011+ AuDbgDentry(d);
5afbbe0d 21012+ dput(d);
b912730e
AM
21013+ }
21014+ AuDbgDentry(dentry);
21015+ }
21016+
21017+ if (d_is_positive(dentry)
21018+ || d_unhashed(dentry)
21019+ || d_unlinked(dentry)
acd2b654
AM
21020+ || !(open_flag & O_CREAT)) {
21021+ err = au_aopen_no_open(file, dentry);
21022+ goto out; /* success */
21023+ }
b912730e
AM
21024+
21025+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
21026+ if (unlikely(err))
21027+ goto out;
21028+
acd2b654 21029+ sb = dentry->d_sb;
b912730e
AM
21030+ parent = dentry->d_parent; /* dir is locked */
21031+ di_write_lock_parent(parent);
5afbbe0d 21032+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
acd2b654
AM
21033+ if (unlikely(err < 0))
21034+ goto out_parent;
b912730e
AM
21035+
21036+ AuDbgDentry(dentry);
acd2b654
AM
21037+ if (d_is_positive(dentry)) {
21038+ err = au_aopen_no_open(file, dentry);
21039+ goto out_parent; /* success */
21040+ }
b912730e 21041+
acd2b654 21042+ args.file = alloc_empty_file(file->f_flags, current_cred());
b912730e
AM
21043+ err = PTR_ERR(args.file);
21044+ if (IS_ERR(args.file))
acd2b654 21045+ goto out_parent;
b912730e 21046+
acd2b654 21047+ bindex = au_dbtop(dentry);
b912730e
AM
21048+ err = au_aopen_or_create(dir, dentry, &args);
21049+ AuTraceErr(err);
21050+ AuDbgFile(args.file);
acd2b654
AM
21051+ file->f_mode = args.file->f_mode & ~FMODE_OPENED;
21052+ did_open = !!(args.file->f_mode & FMODE_OPENED);
21053+ if (!did_open) {
21054+ fput(args.file);
21055+ args.file = NULL;
b912730e 21056+ }
8b6a4947
AM
21057+ di_write_unlock(parent);
21058+ di_write_unlock(dentry);
acd2b654
AM
21059+ if (unlikely(err < 0)) {
21060+ if (args.file)
21061+ fput(args.file);
21062+ goto out_sb;
b912730e 21063+ }
b912730e 21064+
acd2b654
AM
21065+ if (!did_open)
21066+ err = au_aopen_no_open(file, dentry);
8b6a4947 21067+ else {
acd2b654
AM
21068+ aopen_node.h_file = args.file;
21069+ err = au_aopen_do_open(file, dentry, &aopen_node);
8b6a4947 21070+ }
acd2b654
AM
21071+ if (unlikely(err < 0)) {
21072+ if (args.file)
21073+ fput(args.file);
21074+ if (did_open)
21075+ au_lcnt_dec(&args.br->br_nfiles);
b912730e 21076+ }
acd2b654
AM
21077+ goto out_sb; /* success */
21078+
21079+out_parent:
21080+ di_write_unlock(parent);
21081+ di_write_unlock(dentry);
21082+out_sb:
21083+ si_read_unlock(sb);
b912730e 21084+out:
b912730e 21085+ AuTraceErr(err);
acd2b654 21086+ AuDbgFile(file);
b912730e
AM
21087+ return err;
21088+}
21089+
21090+
21091+/* ---------------------------------------------------------------------- */
21092+
4a4d8108
AM
21093+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
21094+ const unsigned char add_entry, aufs_bindex_t bcpup,
5afbbe0d 21095+ aufs_bindex_t btop)
4a4d8108
AM
21096+{
21097+ int err;
21098+ struct dentry *h_parent;
21099+ struct inode *h_dir;
1facf9fc 21100+
027c5e7a 21101+ if (add_entry)
5527c038 21102+ IMustLock(d_inode(parent));
027c5e7a 21103+ else
4a4d8108
AM
21104+ di_write_lock_parent(parent);
21105+
21106+ err = 0;
21107+ if (!au_h_dptr(parent, bcpup)) {
5afbbe0d 21108+ if (btop > bcpup)
c2b27bf2 21109+ err = au_cpup_dirs(dentry, bcpup);
5afbbe0d 21110+ else if (btop < bcpup)
4a4d8108
AM
21111+ err = au_cpdown_dirs(dentry, bcpup);
21112+ else
c2b27bf2 21113+ BUG();
4a4d8108 21114+ }
38d290e6 21115+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) {
4a4d8108 21116+ h_parent = au_h_dptr(parent, bcpup);
5527c038 21117+ h_dir = d_inode(h_parent);
be118d29 21118+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
7e9cd9fe 21119+ err = au_lkup_neg(dentry, bcpup, /*wh*/0);
4a4d8108 21120+ /* todo: no unlock here */
3c1bdaff 21121+ inode_unlock_shared(h_dir);
027c5e7a
AM
21122+
21123+ AuDbg("bcpup %d\n", bcpup);
21124+ if (!err) {
5527c038 21125+ if (d_really_is_negative(dentry))
5afbbe0d 21126+ au_set_h_dptr(dentry, btop, NULL);
4a4d8108
AM
21127+ au_update_dbrange(dentry, /*do_put_zero*/0);
21128+ }
1308ab2a 21129+ }
1facf9fc 21130+
4a4d8108
AM
21131+ if (!add_entry)
21132+ di_write_unlock(parent);
21133+ if (!err)
21134+ err = bcpup; /* success */
1308ab2a 21135+
027c5e7a 21136+ AuTraceErr(err);
4a4d8108
AM
21137+ return err;
21138+}
1facf9fc 21139+
4a4d8108
AM
21140+/*
21141+ * decide the branch and the parent dir where we will create a new entry.
21142+ * returns new bindex or an error.
21143+ * copyup the parent dir if needed.
21144+ */
21145+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
21146+ struct au_wr_dir_args *args)
21147+{
21148+ int err;
392086de 21149+ unsigned int flags;
5afbbe0d 21150+ aufs_bindex_t bcpup, btop, src_btop;
86dc4139
AM
21151+ const unsigned char add_entry
21152+ = au_ftest_wrdir(args->flags, ADD_ENTRY)
38d290e6 21153+ | au_ftest_wrdir(args->flags, TMPFILE);
4a4d8108
AM
21154+ struct super_block *sb;
21155+ struct dentry *parent;
21156+ struct au_sbinfo *sbinfo;
1facf9fc 21157+
4a4d8108
AM
21158+ sb = dentry->d_sb;
21159+ sbinfo = au_sbi(sb);
21160+ parent = dget_parent(dentry);
5afbbe0d
AM
21161+ btop = au_dbtop(dentry);
21162+ bcpup = btop;
4a4d8108
AM
21163+ if (args->force_btgt < 0) {
21164+ if (src_dentry) {
5afbbe0d
AM
21165+ src_btop = au_dbtop(src_dentry);
21166+ if (src_btop < btop)
21167+ bcpup = src_btop;
4a4d8108 21168+ } else if (add_entry) {
392086de
AM
21169+ flags = 0;
21170+ if (au_ftest_wrdir(args->flags, ISDIR))
21171+ au_fset_wbr(flags, DIR);
21172+ err = AuWbrCreate(sbinfo, dentry, flags);
4a4d8108
AM
21173+ bcpup = err;
21174+ }
1facf9fc 21175+
5527c038 21176+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) {
4a4d8108
AM
21177+ if (add_entry)
21178+ err = AuWbrCopyup(sbinfo, dentry);
21179+ else {
21180+ if (!IS_ROOT(dentry)) {
21181+ di_read_lock_parent(parent, !AuLock_IR);
21182+ err = AuWbrCopyup(sbinfo, dentry);
21183+ di_read_unlock(parent, !AuLock_IR);
21184+ } else
21185+ err = AuWbrCopyup(sbinfo, dentry);
21186+ }
21187+ bcpup = err;
21188+ if (unlikely(err < 0))
21189+ goto out;
21190+ }
21191+ } else {
21192+ bcpup = args->force_btgt;
5527c038 21193+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry)));
1308ab2a 21194+ }
027c5e7a 21195+
5afbbe0d 21196+ AuDbg("btop %d, bcpup %d\n", btop, bcpup);
4a4d8108 21197+ err = bcpup;
5afbbe0d 21198+ if (bcpup == btop)
4a4d8108 21199+ goto out; /* success */
4a4d8108
AM
21200+
21201+ /* copyup the new parent into the branch we process */
5afbbe0d 21202+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop);
027c5e7a 21203+ if (err >= 0) {
5527c038 21204+ if (d_really_is_negative(dentry)) {
5afbbe0d
AM
21205+ au_set_h_dptr(dentry, btop, NULL);
21206+ au_set_dbtop(dentry, bcpup);
21207+ au_set_dbbot(dentry, bcpup);
027c5e7a 21208+ }
38d290e6
JR
21209+ AuDebugOn(add_entry
21210+ && !au_ftest_wrdir(args->flags, TMPFILE)
21211+ && !au_h_dptr(dentry, bcpup));
027c5e7a 21212+ }
86dc4139
AM
21213+
21214+out:
21215+ dput(parent);
21216+ return err;
21217+}
21218+
21219+/* ---------------------------------------------------------------------- */
21220+
21221+void au_pin_hdir_unlock(struct au_pin *p)
21222+{
21223+ if (p->hdir)
5afbbe0d 21224+ au_hn_inode_unlock(p->hdir);
86dc4139
AM
21225+}
21226+
c1595e42 21227+int au_pin_hdir_lock(struct au_pin *p)
86dc4139
AM
21228+{
21229+ int err;
21230+
21231+ err = 0;
21232+ if (!p->hdir)
21233+ goto out;
21234+
21235+ /* even if an error happens later, keep this lock */
5afbbe0d 21236+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi);
86dc4139
AM
21237+
21238+ err = -EBUSY;
5527c038 21239+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent)))
86dc4139
AM
21240+ goto out;
21241+
21242+ err = 0;
21243+ if (p->h_dentry)
21244+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode,
21245+ p->h_parent, p->br);
21246+
21247+out:
21248+ return err;
21249+}
21250+
21251+int au_pin_hdir_relock(struct au_pin *p)
21252+{
21253+ int err, i;
21254+ struct inode *h_i;
21255+ struct dentry *h_d[] = {
21256+ p->h_dentry,
21257+ p->h_parent
21258+ };
21259+
21260+ err = au_pin_hdir_lock(p);
21261+ if (unlikely(err))
21262+ goto out;
21263+
21264+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) {
21265+ if (!h_d[i])
21266+ continue;
5527c038
JR
21267+ if (d_is_positive(h_d[i])) {
21268+ h_i = d_inode(h_d[i]);
86dc4139 21269+ err = !h_i->i_nlink;
5527c038 21270+ }
86dc4139
AM
21271+ }
21272+
21273+out:
21274+ return err;
21275+}
21276+
5afbbe0d 21277+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task)
86dc4139 21278+{
eca34b5c 21279+ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task);
86dc4139
AM
21280+}
21281+
21282+void au_pin_hdir_acquire_nest(struct au_pin *p)
21283+{
21284+ if (p->hdir) {
5afbbe0d 21285+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map,
86dc4139
AM
21286+ p->lsc_hi, 0, NULL, _RET_IP_);
21287+ au_pin_hdir_set_owner(p, current);
21288+ }
dece6358 21289+}
1facf9fc 21290+
86dc4139
AM
21291+void au_pin_hdir_release(struct au_pin *p)
21292+{
21293+ if (p->hdir) {
21294+ au_pin_hdir_set_owner(p, p->task);
5afbbe0d 21295+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, 1, _RET_IP_);
86dc4139
AM
21296+ }
21297+}
1308ab2a 21298+
4a4d8108 21299+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 21300+{
4a4d8108
AM
21301+ if (pin && pin->parent)
21302+ return au_h_dptr(pin->parent, pin->bindex);
21303+ return NULL;
dece6358 21304+}
1facf9fc 21305+
4a4d8108 21306+void au_unpin(struct au_pin *p)
dece6358 21307+{
86dc4139
AM
21308+ if (p->hdir)
21309+ au_pin_hdir_unlock(p);
e49829fe 21310+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
b4510431 21311+ vfsub_mnt_drop_write(p->h_mnt);
4a4d8108
AM
21312+ if (!p->hdir)
21313+ return;
1facf9fc 21314+
4a4d8108
AM
21315+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21316+ di_read_unlock(p->parent, AuLock_IR);
21317+ iput(p->hdir->hi_inode);
21318+ dput(p->parent);
21319+ p->parent = NULL;
21320+ p->hdir = NULL;
21321+ p->h_mnt = NULL;
86dc4139 21322+ /* do not clear p->task */
4a4d8108 21323+}
1308ab2a 21324+
4a4d8108
AM
21325+int au_do_pin(struct au_pin *p)
21326+{
21327+ int err;
21328+ struct super_block *sb;
4a4d8108
AM
21329+ struct inode *h_dir;
21330+
21331+ err = 0;
21332+ sb = p->dentry->d_sb;
86dc4139 21333+ p->br = au_sbr(sb, p->bindex);
4a4d8108
AM
21334+ if (IS_ROOT(p->dentry)) {
21335+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21336+ p->h_mnt = au_br_mnt(p->br);
b4510431 21337+ err = vfsub_mnt_want_write(p->h_mnt);
4a4d8108
AM
21338+ if (unlikely(err)) {
21339+ au_fclr_pin(p->flags, MNT_WRITE);
21340+ goto out_err;
21341+ }
21342+ }
dece6358 21343+ goto out;
1facf9fc 21344+ }
21345+
86dc4139 21346+ p->h_dentry = NULL;
5afbbe0d 21347+ if (p->bindex <= au_dbbot(p->dentry))
86dc4139 21348+ p->h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 21349+
4a4d8108
AM
21350+ p->parent = dget_parent(p->dentry);
21351+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21352+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 21353+
4a4d8108 21354+ h_dir = NULL;
86dc4139 21355+ p->h_parent = au_h_dptr(p->parent, p->bindex);
5527c038 21356+ p->hdir = au_hi(d_inode(p->parent), p->bindex);
4a4d8108
AM
21357+ if (p->hdir)
21358+ h_dir = p->hdir->hi_inode;
dece6358 21359+
b752ccd1
AM
21360+ /*
21361+ * udba case, or
21362+ * if DI_LOCKED is not set, then p->parent may be different
21363+ * and h_parent can be NULL.
21364+ */
86dc4139 21365+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) {
e49829fe 21366+ err = -EBUSY;
4a4d8108
AM
21367+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21368+ di_read_unlock(p->parent, AuLock_IR);
21369+ dput(p->parent);
21370+ p->parent = NULL;
21371+ goto out_err;
21372+ }
1308ab2a 21373+
4a4d8108 21374+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21375+ p->h_mnt = au_br_mnt(p->br);
b4510431 21376+ err = vfsub_mnt_want_write(p->h_mnt);
dece6358 21377+ if (unlikely(err)) {
4a4d8108 21378+ au_fclr_pin(p->flags, MNT_WRITE);
86dc4139
AM
21379+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21380+ di_read_unlock(p->parent, AuLock_IR);
21381+ dput(p->parent);
21382+ p->parent = NULL;
21383+ goto out_err;
dece6358
AM
21384+ }
21385+ }
4a4d8108 21386+
86dc4139
AM
21387+ au_igrab(h_dir);
21388+ err = au_pin_hdir_lock(p);
21389+ if (!err)
21390+ goto out; /* success */
21391+
076b876e
AM
21392+ au_unpin(p);
21393+
4f0767ce 21394+out_err:
4a4d8108
AM
21395+ pr_err("err %d\n", err);
21396+ err = au_busy_or_stale();
4f0767ce 21397+out:
1facf9fc 21398+ return err;
21399+}
21400+
4a4d8108
AM
21401+void au_pin_init(struct au_pin *p, struct dentry *dentry,
21402+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
21403+ unsigned int udba, unsigned char flags)
21404+{
21405+ p->dentry = dentry;
21406+ p->udba = udba;
21407+ p->lsc_di = lsc_di;
21408+ p->lsc_hi = lsc_hi;
21409+ p->flags = flags;
21410+ p->bindex = bindex;
21411+
21412+ p->parent = NULL;
21413+ p->hdir = NULL;
21414+ p->h_mnt = NULL;
86dc4139
AM
21415+
21416+ p->h_dentry = NULL;
21417+ p->h_parent = NULL;
21418+ p->br = NULL;
21419+ p->task = current;
4a4d8108
AM
21420+}
21421+
21422+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
21423+ unsigned int udba, unsigned char flags)
21424+{
21425+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
21426+ udba, flags);
21427+ return au_do_pin(pin);
21428+}
21429+
dece6358
AM
21430+/* ---------------------------------------------------------------------- */
21431+
1308ab2a 21432+/*
4a4d8108
AM
21433+ * ->setattr() and ->getattr() are called in various cases.
21434+ * chmod, stat: dentry is revalidated.
21435+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
21436+ * unhashed.
21437+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 21438+ */
027c5e7a 21439+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
c1595e42 21440+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 21441+{
4a4d8108 21442+ int err;
4a4d8108 21443+ struct dentry *parent;
1facf9fc 21444+
1308ab2a 21445+ err = 0;
027c5e7a 21446+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
21447+ parent = dget_parent(dentry);
21448+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 21449+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
21450+ di_read_unlock(parent, AuLock_IR);
21451+ dput(parent);
dece6358 21452+ }
1facf9fc 21453+
4a4d8108 21454+ AuTraceErr(err);
1308ab2a 21455+ return err;
21456+}
dece6358 21457+
c1595e42
JR
21458+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
21459+ struct au_icpup_args *a)
1308ab2a 21460+{
21461+ int err;
4a4d8108 21462+ loff_t sz;
5afbbe0d 21463+ aufs_bindex_t btop, ibtop;
4a4d8108
AM
21464+ struct dentry *hi_wh, *parent;
21465+ struct inode *inode;
4a4d8108
AM
21466+ struct au_wr_dir_args wr_dir_args = {
21467+ .force_btgt = -1,
21468+ .flags = 0
21469+ };
21470+
2000de60 21471+ if (d_is_dir(dentry))
4a4d8108
AM
21472+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
21473+ /* plink or hi_wh() case */
5afbbe0d 21474+ btop = au_dbtop(dentry);
5527c038 21475+ inode = d_inode(dentry);
5afbbe0d
AM
21476+ ibtop = au_ibtop(inode);
21477+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode))
21478+ wr_dir_args.force_btgt = ibtop;
4a4d8108
AM
21479+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
21480+ if (unlikely(err < 0))
21481+ goto out;
21482+ a->btgt = err;
5afbbe0d 21483+ if (err != btop)
4a4d8108
AM
21484+ au_fset_icpup(a->flags, DID_CPUP);
21485+
21486+ err = 0;
21487+ a->pin_flags = AuPin_MNT_WRITE;
21488+ parent = NULL;
21489+ if (!IS_ROOT(dentry)) {
21490+ au_fset_pin(a->pin_flags, DI_LOCKED);
21491+ parent = dget_parent(dentry);
21492+ di_write_lock_parent(parent);
21493+ }
21494+
21495+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
21496+ if (unlikely(err))
21497+ goto out_parent;
21498+
4a4d8108 21499+ sz = -1;
5afbbe0d 21500+ a->h_path.dentry = au_h_dptr(dentry, btop);
5527c038 21501+ a->h_inode = d_inode(a->h_path.dentry);
c1595e42 21502+ if (ia && (ia->ia_valid & ATTR_SIZE)) {
be118d29 21503+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
c1595e42
JR
21504+ if (ia->ia_size < i_size_read(a->h_inode))
21505+ sz = ia->ia_size;
3c1bdaff 21506+ inode_unlock_shared(a->h_inode);
c1595e42 21507+ }
4a4d8108 21508+
4a4d8108 21509+ hi_wh = NULL;
027c5e7a 21510+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
21511+ hi_wh = au_hi_wh(inode, a->btgt);
21512+ if (!hi_wh) {
c2b27bf2
AM
21513+ struct au_cp_generic cpg = {
21514+ .dentry = dentry,
21515+ .bdst = a->btgt,
21516+ .bsrc = -1,
21517+ .len = sz,
21518+ .pin = &a->pin
21519+ };
21520+ err = au_sio_cpup_wh(&cpg, /*file*/NULL);
4a4d8108
AM
21521+ if (unlikely(err))
21522+ goto out_unlock;
21523+ hi_wh = au_hi_wh(inode, a->btgt);
21524+ /* todo: revalidate hi_wh? */
21525+ }
21526+ }
21527+
21528+ if (parent) {
21529+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
21530+ di_downgrade_lock(parent, AuLock_IR);
21531+ dput(parent);
21532+ parent = NULL;
21533+ }
21534+ if (!au_ftest_icpup(a->flags, DID_CPUP))
21535+ goto out; /* success */
21536+
21537+ if (!d_unhashed(dentry)) {
c2b27bf2
AM
21538+ struct au_cp_generic cpg = {
21539+ .dentry = dentry,
21540+ .bdst = a->btgt,
5afbbe0d 21541+ .bsrc = btop,
c2b27bf2
AM
21542+ .len = sz,
21543+ .pin = &a->pin,
21544+ .flags = AuCpup_DTIME | AuCpup_HOPEN
21545+ };
21546+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
21547+ if (!err)
21548+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21549+ } else if (!hi_wh)
21550+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21551+ else
21552+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 21553+
4f0767ce 21554+out_unlock:
5527c038 21555+ a->h_inode = d_inode(a->h_path.dentry);
86dc4139 21556+ if (!err)
dece6358 21557+ goto out; /* success */
4a4d8108 21558+ au_unpin(&a->pin);
4f0767ce 21559+out_parent:
4a4d8108
AM
21560+ if (parent) {
21561+ di_write_unlock(parent);
21562+ dput(parent);
21563+ }
4f0767ce 21564+out:
86dc4139 21565+ if (!err)
febd17d6 21566+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
1facf9fc 21567+ return err;
21568+}
21569+
4a4d8108 21570+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 21571+{
4a4d8108 21572+ int err;
523b37e3 21573+ struct inode *inode, *delegated;
4a4d8108
AM
21574+ struct super_block *sb;
21575+ struct file *file;
21576+ struct au_icpup_args *a;
1facf9fc 21577+
5527c038 21578+ inode = d_inode(dentry);
4a4d8108 21579+ IMustLock(inode);
dece6358 21580+
f2c43d5f
AM
21581+ err = setattr_prepare(dentry, ia);
21582+ if (unlikely(err))
21583+ goto out;
21584+
4a4d8108
AM
21585+ err = -ENOMEM;
21586+ a = kzalloc(sizeof(*a), GFP_NOFS);
21587+ if (unlikely(!a))
21588+ goto out;
1facf9fc 21589+
4a4d8108
AM
21590+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
21591+ ia->ia_valid &= ~ATTR_MODE;
dece6358 21592+
4a4d8108
AM
21593+ file = NULL;
21594+ sb = dentry->d_sb;
e49829fe
JR
21595+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21596+ if (unlikely(err))
21597+ goto out_kfree;
21598+
4a4d8108
AM
21599+ if (ia->ia_valid & ATTR_FILE) {
21600+ /* currently ftruncate(2) only */
7e9cd9fe 21601+ AuDebugOn(!d_is_reg(dentry));
4a4d8108 21602+ file = ia->ia_file;
521ced18
JR
21603+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
21604+ /*fi_lsc*/0);
4a4d8108
AM
21605+ if (unlikely(err))
21606+ goto out_si;
21607+ ia->ia_file = au_hf_top(file);
21608+ a->udba = AuOpt_UDBA_NONE;
21609+ } else {
21610+ /* fchmod() doesn't pass ia_file */
21611+ a->udba = au_opt_udba(sb);
027c5e7a
AM
21612+ di_write_lock_child(dentry);
21613+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
21614+ if (d_unhashed(dentry))
21615+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
21616+ if (a->udba != AuOpt_UDBA_NONE) {
21617+ AuDebugOn(IS_ROOT(dentry));
21618+ err = au_reval_for_attr(dentry, au_sigen(sb));
21619+ if (unlikely(err))
21620+ goto out_dentry;
21621+ }
dece6358 21622+ }
dece6358 21623+
4a4d8108
AM
21624+ err = au_pin_and_icpup(dentry, ia, a);
21625+ if (unlikely(err < 0))
21626+ goto out_dentry;
21627+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
21628+ ia->ia_file = NULL;
21629+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 21630+ }
dece6358 21631+
4a4d8108
AM
21632+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
21633+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
21634+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 21635+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
21636+ if (unlikely(err))
21637+ goto out_unlock;
21638+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
21639+ && (ia->ia_valid & ATTR_CTIME)) {
86dc4139 21640+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
4a4d8108
AM
21641+ if (unlikely(err))
21642+ goto out_unlock;
21643+ }
dece6358 21644+
4a4d8108
AM
21645+ if (ia->ia_valid & ATTR_SIZE) {
21646+ struct file *f;
1308ab2a 21647+
953406b4 21648+ if (ia->ia_size < i_size_read(inode))
4a4d8108 21649+ /* unmap only */
953406b4 21650+ truncate_setsize(inode, ia->ia_size);
1308ab2a 21651+
4a4d8108
AM
21652+ f = NULL;
21653+ if (ia->ia_valid & ATTR_FILE)
21654+ f = ia->ia_file;
febd17d6 21655+ inode_unlock(a->h_inode);
4a4d8108 21656+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
febd17d6 21657+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
523b37e3
AM
21658+ } else {
21659+ delegated = NULL;
21660+ while (1) {
21661+ err = vfsub_notify_change(&a->h_path, ia, &delegated);
21662+ if (delegated) {
21663+ err = break_deleg_wait(&delegated);
21664+ if (!err)
21665+ continue;
21666+ }
21667+ break;
21668+ }
21669+ }
8cdd5066
JR
21670+ /*
21671+ * regardless aufs 'acl' option setting.
21672+ * why don't all acl-aware fs call this func from their ->setattr()?
21673+ */
21674+ if (!err && (ia->ia_valid & ATTR_MODE))
21675+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode);
4a4d8108
AM
21676+ if (!err)
21677+ au_cpup_attr_changeable(inode);
1308ab2a 21678+
4f0767ce 21679+out_unlock:
febd17d6 21680+ inode_unlock(a->h_inode);
4a4d8108 21681+ au_unpin(&a->pin);
027c5e7a 21682+ if (unlikely(err))
5afbbe0d 21683+ au_update_dbtop(dentry);
4f0767ce 21684+out_dentry:
4a4d8108
AM
21685+ di_write_unlock(dentry);
21686+ if (file) {
21687+ fi_write_unlock(file);
21688+ ia->ia_file = file;
21689+ ia->ia_valid |= ATTR_FILE;
21690+ }
4f0767ce 21691+out_si:
4a4d8108 21692+ si_read_unlock(sb);
e49829fe 21693+out_kfree:
9f237c51 21694+ au_kfree_rcu(a);
4f0767ce 21695+out:
4a4d8108
AM
21696+ AuTraceErr(err);
21697+ return err;
1facf9fc 21698+}
21699+
c1595e42
JR
21700+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
21701+static int au_h_path_to_set_attr(struct dentry *dentry,
21702+ struct au_icpup_args *a, struct path *h_path)
21703+{
21704+ int err;
21705+ struct super_block *sb;
21706+
21707+ sb = dentry->d_sb;
21708+ a->udba = au_opt_udba(sb);
21709+ /* no d_unlinked(), to set UDBA_NONE for root */
21710+ if (d_unhashed(dentry))
21711+ a->udba = AuOpt_UDBA_NONE;
21712+ if (a->udba != AuOpt_UDBA_NONE) {
21713+ AuDebugOn(IS_ROOT(dentry));
21714+ err = au_reval_for_attr(dentry, au_sigen(sb));
21715+ if (unlikely(err))
21716+ goto out;
21717+ }
21718+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a);
21719+ if (unlikely(err < 0))
21720+ goto out;
21721+
21722+ h_path->dentry = a->h_path.dentry;
21723+ h_path->mnt = au_sbr_mnt(sb, a->btgt);
21724+
21725+out:
21726+ return err;
21727+}
21728+
f2c43d5f
AM
21729+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
21730+ struct au_sxattr *arg)
c1595e42
JR
21731+{
21732+ int err;
21733+ struct path h_path;
21734+ struct super_block *sb;
21735+ struct au_icpup_args *a;
5afbbe0d 21736+ struct inode *h_inode;
c1595e42 21737+
c1595e42
JR
21738+ IMustLock(inode);
21739+
21740+ err = -ENOMEM;
21741+ a = kzalloc(sizeof(*a), GFP_NOFS);
21742+ if (unlikely(!a))
21743+ goto out;
21744+
21745+ sb = dentry->d_sb;
21746+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21747+ if (unlikely(err))
21748+ goto out_kfree;
21749+
21750+ h_path.dentry = NULL; /* silence gcc */
21751+ di_write_lock_child(dentry);
21752+ err = au_h_path_to_set_attr(dentry, a, &h_path);
21753+ if (unlikely(err))
21754+ goto out_di;
21755+
febd17d6 21756+ inode_unlock(a->h_inode);
c1595e42
JR
21757+ switch (arg->type) {
21758+ case AU_XATTR_SET:
5afbbe0d 21759+ AuDebugOn(d_is_negative(h_path.dentry));
c1595e42
JR
21760+ err = vfsub_setxattr(h_path.dentry,
21761+ arg->u.set.name, arg->u.set.value,
21762+ arg->u.set.size, arg->u.set.flags);
21763+ break;
c1595e42
JR
21764+ case AU_ACL_SET:
21765+ err = -EOPNOTSUPP;
5527c038 21766+ h_inode = d_inode(h_path.dentry);
c1595e42 21767+ if (h_inode->i_op->set_acl)
f2c43d5f 21768+ /* this will call posix_acl_update_mode */
c1595e42
JR
21769+ err = h_inode->i_op->set_acl(h_inode,
21770+ arg->u.acl_set.acl,
21771+ arg->u.acl_set.type);
21772+ break;
21773+ }
21774+ if (!err)
21775+ au_cpup_attr_timesizes(inode);
21776+
21777+ au_unpin(&a->pin);
21778+ if (unlikely(err))
5afbbe0d 21779+ au_update_dbtop(dentry);
c1595e42
JR
21780+
21781+out_di:
21782+ di_write_unlock(dentry);
21783+ si_read_unlock(sb);
21784+out_kfree:
9f237c51 21785+ au_kfree_rcu(a);
c1595e42
JR
21786+out:
21787+ AuTraceErr(err);
21788+ return err;
21789+}
21790+#endif
21791+
4a4d8108
AM
21792+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
21793+ unsigned int nlink)
1facf9fc 21794+{
9dbd164d
AM
21795+ unsigned int n;
21796+
4a4d8108 21797+ inode->i_mode = st->mode;
86dc4139
AM
21798+ /* don't i_[ug]id_write() here */
21799+ inode->i_uid = st->uid;
21800+ inode->i_gid = st->gid;
4a4d8108
AM
21801+ inode->i_atime = st->atime;
21802+ inode->i_mtime = st->mtime;
21803+ inode->i_ctime = st->ctime;
1facf9fc 21804+
4a4d8108
AM
21805+ au_cpup_attr_nlink(inode, /*force*/0);
21806+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
21807+ n = inode->i_nlink;
21808+ n -= nlink;
21809+ n += st->nlink;
f6b6e03d 21810+ smp_mb(); /* for i_nlink */
7eafdf33 21811+ /* 0 can happen */
92d182d2 21812+ set_nlink(inode, n);
4a4d8108 21813+ }
1facf9fc 21814+
4a4d8108
AM
21815+ spin_lock(&inode->i_lock);
21816+ inode->i_blocks = st->blocks;
21817+ i_size_write(inode, st->size);
21818+ spin_unlock(&inode->i_lock);
1facf9fc 21819+}
21820+
c1595e42 21821+/*
f2c43d5f 21822+ * common routine for aufs_getattr() and au_getxattr().
c1595e42
JR
21823+ * returns zero or negative (an error).
21824+ * @dentry will be read-locked in success.
21825+ */
a2654f78
AM
21826+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
21827+ int locked)
1facf9fc 21828+{
4a4d8108 21829+ int err;
076b876e 21830+ unsigned int mnt_flags, sigen;
c1595e42 21831+ unsigned char udba_none;
4a4d8108 21832+ aufs_bindex_t bindex;
4a4d8108
AM
21833+ struct super_block *sb, *h_sb;
21834+ struct inode *inode;
1facf9fc 21835+
c1595e42
JR
21836+ h_path->mnt = NULL;
21837+ h_path->dentry = NULL;
21838+
21839+ err = 0;
4a4d8108 21840+ sb = dentry->d_sb;
4a4d8108
AM
21841+ mnt_flags = au_mntflags(sb);
21842+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 21843+
a2654f78
AM
21844+ if (unlikely(locked))
21845+ goto body; /* skip locking dinfo */
21846+
4a4d8108 21847+ /* support fstat(2) */
027c5e7a 21848+ if (!d_unlinked(dentry) && !udba_none) {
076b876e 21849+ sigen = au_sigen(sb);
027c5e7a
AM
21850+ err = au_digen_test(dentry, sigen);
21851+ if (!err) {
4a4d8108 21852+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a 21853+ err = au_dbrange_test(dentry);
c1595e42
JR
21854+ if (unlikely(err)) {
21855+ di_read_unlock(dentry, AuLock_IR);
21856+ goto out;
21857+ }
027c5e7a 21858+ } else {
4a4d8108
AM
21859+ AuDebugOn(IS_ROOT(dentry));
21860+ di_write_lock_child(dentry);
027c5e7a
AM
21861+ err = au_dbrange_test(dentry);
21862+ if (!err)
21863+ err = au_reval_for_attr(dentry, sigen);
c1595e42
JR
21864+ if (!err)
21865+ di_downgrade_lock(dentry, AuLock_IR);
21866+ else {
21867+ di_write_unlock(dentry);
21868+ goto out;
21869+ }
4a4d8108
AM
21870+ }
21871+ } else
21872+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 21873+
a2654f78 21874+body:
5527c038 21875+ inode = d_inode(dentry);
5afbbe0d 21876+ bindex = au_ibtop(inode);
c1595e42
JR
21877+ h_path->mnt = au_sbr_mnt(sb, bindex);
21878+ h_sb = h_path->mnt->mnt_sb;
21879+ if (!force
21880+ && !au_test_fs_bad_iattr(h_sb)
21881+ && udba_none)
21882+ goto out; /* success */
1facf9fc 21883+
5afbbe0d 21884+ if (au_dbtop(dentry) == bindex)
c1595e42 21885+ h_path->dentry = au_h_dptr(dentry, bindex);
4a4d8108 21886+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
c1595e42
JR
21887+ h_path->dentry = au_plink_lkup(inode, bindex);
21888+ if (IS_ERR(h_path->dentry))
21889+ /* pretending success */
21890+ h_path->dentry = NULL;
21891+ else
21892+ dput(h_path->dentry);
4a4d8108 21893+ }
c1595e42
JR
21894+
21895+out:
21896+ return err;
21897+}
21898+
521ced18
JR
21899+static int aufs_getattr(const struct path *path, struct kstat *st,
21900+ u32 request, unsigned int query)
c1595e42
JR
21901+{
21902+ int err;
21903+ unsigned char positive;
21904+ struct path h_path;
521ced18 21905+ struct dentry *dentry;
c1595e42
JR
21906+ struct inode *inode;
21907+ struct super_block *sb;
21908+
521ced18 21909+ dentry = path->dentry;
5527c038 21910+ inode = d_inode(dentry);
c1595e42
JR
21911+ sb = dentry->d_sb;
21912+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21913+ if (unlikely(err))
21914+ goto out;
a2654f78 21915+ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0);
c1595e42
JR
21916+ if (unlikely(err))
21917+ goto out_si;
c06a8ce3 21918+ if (unlikely(!h_path.dentry))
c1595e42 21919+ /* illegally overlapped or something */
4a4d8108
AM
21920+ goto out_fill; /* pretending success */
21921+
5527c038 21922+ positive = d_is_positive(h_path.dentry);
4a4d8108 21923+ if (positive)
521ced18
JR
21924+ /* no vfsub version */
21925+ err = vfs_getattr(&h_path, st, request, query);
4a4d8108
AM
21926+ if (!err) {
21927+ if (positive)
c06a8ce3 21928+ au_refresh_iattr(inode, st,
5527c038 21929+ d_inode(h_path.dentry)->i_nlink);
4a4d8108 21930+ goto out_fill; /* success */
1facf9fc 21931+ }
7f207e10 21932+ AuTraceErr(err);
c1595e42 21933+ goto out_di;
4a4d8108 21934+
4f0767ce 21935+out_fill:
4a4d8108 21936+ generic_fillattr(inode, st);
c1595e42 21937+out_di:
4a4d8108 21938+ di_read_unlock(dentry, AuLock_IR);
c1595e42 21939+out_si:
4a4d8108 21940+ si_read_unlock(sb);
7f207e10
AM
21941+out:
21942+ AuTraceErr(err);
4a4d8108 21943+ return err;
1facf9fc 21944+}
21945+
21946+/* ---------------------------------------------------------------------- */
21947+
febd17d6
JR
21948+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode,
21949+ struct delayed_call *done)
4a4d8108 21950+{
c2c0f25c 21951+ const char *ret;
c2c0f25c 21952+ struct dentry *h_dentry;
febd17d6 21953+ struct inode *h_inode;
4a4d8108 21954+ int err;
c2c0f25c 21955+ aufs_bindex_t bindex;
1facf9fc 21956+
79b8bda9 21957+ ret = NULL; /* suppress a warning */
febd17d6
JR
21958+ err = -ECHILD;
21959+ if (!dentry)
21960+ goto out;
21961+
027c5e7a
AM
21962+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
21963+ if (unlikely(err))
c2c0f25c 21964+ goto out;
027c5e7a
AM
21965+
21966+ err = au_d_hashed_positive(dentry);
c2c0f25c
AM
21967+ if (unlikely(err))
21968+ goto out_unlock;
21969+
21970+ err = -EINVAL;
21971+ inode = d_inode(dentry);
5afbbe0d 21972+ bindex = au_ibtop(inode);
c2c0f25c 21973+ h_inode = au_h_iptr(inode, bindex);
febd17d6 21974+ if (unlikely(!h_inode->i_op->get_link))
c2c0f25c
AM
21975+ goto out_unlock;
21976+
21977+ err = -EBUSY;
21978+ h_dentry = NULL;
5afbbe0d 21979+ if (au_dbtop(dentry) <= bindex) {
c2c0f25c
AM
21980+ h_dentry = au_h_dptr(dentry, bindex);
21981+ if (h_dentry)
21982+ dget(h_dentry);
027c5e7a 21983+ }
c2c0f25c
AM
21984+ if (!h_dentry) {
21985+ h_dentry = d_find_any_alias(h_inode);
21986+ if (IS_ERR(h_dentry)) {
21987+ err = PTR_ERR(h_dentry);
febd17d6 21988+ goto out_unlock;
c2c0f25c
AM
21989+ }
21990+ }
21991+ if (unlikely(!h_dentry))
febd17d6 21992+ goto out_unlock;
1facf9fc 21993+
c2c0f25c 21994+ err = 0;
062440b3 21995+ AuDbg("%ps\n", h_inode->i_op->get_link);
c2c0f25c 21996+ AuDbgDentry(h_dentry);
f2c43d5f 21997+ ret = vfs_get_link(h_dentry, done);
c2c0f25c 21998+ dput(h_dentry);
febd17d6
JR
21999+ if (IS_ERR(ret))
22000+ err = PTR_ERR(ret);
c2c0f25c 22001+
c2c0f25c
AM
22002+out_unlock:
22003+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 22004+out:
c2c0f25c
AM
22005+ if (unlikely(err))
22006+ ret = ERR_PTR(err);
22007+ AuTraceErrPtr(ret);
22008+ return ret;
4a4d8108 22009+}
1facf9fc 22010+
4a4d8108 22011+/* ---------------------------------------------------------------------- */
1facf9fc 22012+
e2f27e51
AM
22013+static int au_is_special(struct inode *inode)
22014+{
22015+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK));
22016+}
22017+
acd2b654
AM
22018+static int aufs_update_time(struct inode *inode, struct timespec64 *ts,
22019+ int flags)
4a4d8108 22020+{
0c3ec466 22021+ int err;
e2f27e51 22022+ aufs_bindex_t bindex;
0c3ec466
AM
22023+ struct super_block *sb;
22024+ struct inode *h_inode;
e2f27e51 22025+ struct vfsmount *h_mnt;
0c3ec466
AM
22026+
22027+ sb = inode->i_sb;
e2f27e51
AM
22028+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode),
22029+ "unexpected s_flags 0x%lx", sb->s_flags);
22030+
0c3ec466
AM
22031+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
22032+ lockdep_off();
22033+ si_read_lock(sb, AuLock_FLUSH);
22034+ ii_write_lock_child(inode);
e2f27e51
AM
22035+
22036+ err = 0;
22037+ bindex = au_ibtop(inode);
22038+ h_inode = au_h_iptr(inode, bindex);
22039+ if (!au_test_ro(sb, bindex, inode)) {
22040+ h_mnt = au_sbr_mnt(sb, bindex);
22041+ err = vfsub_mnt_want_write(h_mnt);
22042+ if (!err) {
22043+ err = vfsub_update_time(h_inode, ts, flags);
22044+ vfsub_mnt_drop_write(h_mnt);
22045+ }
22046+ } else if (au_is_special(h_inode)) {
22047+ /*
22048+ * Never copy-up here.
22049+ * These special files may already be opened and used for
22050+ * communicating. If we copied it up, then the communication
22051+ * would be corrupted.
22052+ */
22053+ AuWarn1("timestamps for i%lu are ignored "
22054+ "since it is on readonly branch (hi%lu).\n",
22055+ inode->i_ino, h_inode->i_ino);
22056+ } else if (flags & ~S_ATIME) {
22057+ err = -EIO;
22058+ AuIOErr1("unexpected flags 0x%x\n", flags);
22059+ AuDebugOn(1);
22060+ }
22061+
38d290e6
JR
22062+ if (!err)
22063+ au_cpup_attr_timesizes(inode);
0c3ec466
AM
22064+ ii_write_unlock(inode);
22065+ si_read_unlock(sb);
22066+ lockdep_on();
38d290e6
JR
22067+
22068+ if (!err && (flags & S_VERSION))
22069+ inode_inc_iversion(inode);
22070+
0c3ec466 22071+ return err;
4a4d8108 22072+}
1facf9fc 22073+
4a4d8108 22074+/* ---------------------------------------------------------------------- */
1308ab2a 22075+
b95c5147
AM
22076+/* no getattr version will be set by module.c:aufs_init() */
22077+struct inode_operations aufs_iop_nogetattr[AuIop_Last],
22078+ aufs_iop[] = {
22079+ [AuIop_SYMLINK] = {
22080+ .permission = aufs_permission,
c1595e42 22081+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22082+ .get_acl = aufs_get_acl,
22083+ .set_acl = aufs_set_acl, /* unsupport for symlink? */
c1595e42
JR
22084+#endif
22085+
b95c5147
AM
22086+ .setattr = aufs_setattr,
22087+ .getattr = aufs_getattr,
0c3ec466 22088+
c1595e42 22089+#ifdef CONFIG_AUFS_XATTR
b95c5147 22090+ .listxattr = aufs_listxattr,
c1595e42
JR
22091+#endif
22092+
febd17d6 22093+ .get_link = aufs_get_link,
0c3ec466 22094+
b95c5147
AM
22095+ /* .update_time = aufs_update_time */
22096+ },
22097+ [AuIop_DIR] = {
22098+ .create = aufs_create,
22099+ .lookup = aufs_lookup,
22100+ .link = aufs_link,
22101+ .unlink = aufs_unlink,
22102+ .symlink = aufs_symlink,
22103+ .mkdir = aufs_mkdir,
22104+ .rmdir = aufs_rmdir,
22105+ .mknod = aufs_mknod,
22106+ .rename = aufs_rename,
22107+
22108+ .permission = aufs_permission,
c1595e42 22109+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22110+ .get_acl = aufs_get_acl,
22111+ .set_acl = aufs_set_acl,
c1595e42
JR
22112+#endif
22113+
b95c5147
AM
22114+ .setattr = aufs_setattr,
22115+ .getattr = aufs_getattr,
0c3ec466 22116+
c1595e42 22117+#ifdef CONFIG_AUFS_XATTR
b95c5147 22118+ .listxattr = aufs_listxattr,
c1595e42
JR
22119+#endif
22120+
b95c5147
AM
22121+ .update_time = aufs_update_time,
22122+ .atomic_open = aufs_atomic_open,
22123+ .tmpfile = aufs_tmpfile
22124+ },
22125+ [AuIop_OTHER] = {
22126+ .permission = aufs_permission,
c1595e42 22127+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22128+ .get_acl = aufs_get_acl,
22129+ .set_acl = aufs_set_acl,
c1595e42
JR
22130+#endif
22131+
b95c5147
AM
22132+ .setattr = aufs_setattr,
22133+ .getattr = aufs_getattr,
0c3ec466 22134+
c1595e42 22135+#ifdef CONFIG_AUFS_XATTR
b95c5147 22136+ .listxattr = aufs_listxattr,
c1595e42
JR
22137+#endif
22138+
b95c5147
AM
22139+ .update_time = aufs_update_time
22140+ }
4a4d8108 22141+};
7f207e10 22142diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
eca34b5c
AM
22143--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
22144+++ linux/fs/aufs/i_op_del.c 2019-07-11 15:42:14.468904634 +0200
eca801bf 22145@@ -0,0 +1,513 @@
cd7a4cd9 22146+// SPDX-License-Identifier: GPL-2.0
1facf9fc 22147+/*
ba1aed25 22148+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 22149+ *
22150+ * This program, aufs is free software; you can redistribute it and/or modify
22151+ * it under the terms of the GNU General Public License as published by
22152+ * the Free Software Foundation; either version 2 of the License, or
22153+ * (at your option) any later version.
dece6358
AM
22154+ *
22155+ * This program is distributed in the hope that it will be useful,
22156+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22157+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22158+ * GNU General Public License for more details.
22159+ *
22160+ * You should have received a copy of the GNU General Public License
523b37e3 22161+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22162+ */
22163+
22164+/*
4a4d8108 22165+ * inode operations (del entry)
1308ab2a 22166+ */
dece6358 22167+
eca801bf 22168+#include <linux/iversion.h>
1308ab2a 22169+#include "aufs.h"
dece6358 22170+
4a4d8108
AM
22171+/*
22172+ * decide if a new whiteout for @dentry is necessary or not.
22173+ * when it is necessary, prepare the parent dir for the upper branch whose
22174+ * branch index is @bcpup for creation. the actual creation of the whiteout will
22175+ * be done by caller.
22176+ * return value:
22177+ * 0: wh is unnecessary
22178+ * plus: wh is necessary
22179+ * minus: error
22180+ */
22181+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 22182+{
4a4d8108 22183+ int need_wh, err;
5afbbe0d 22184+ aufs_bindex_t btop;
4a4d8108 22185+ struct super_block *sb;
dece6358 22186+
4a4d8108 22187+ sb = dentry->d_sb;
5afbbe0d 22188+ btop = au_dbtop(dentry);
4a4d8108 22189+ if (*bcpup < 0) {
5afbbe0d
AM
22190+ *bcpup = btop;
22191+ if (au_test_ro(sb, btop, d_inode(dentry))) {
4a4d8108
AM
22192+ err = AuWbrCopyup(au_sbi(sb), dentry);
22193+ *bcpup = err;
22194+ if (unlikely(err < 0))
22195+ goto out;
22196+ }
22197+ } else
5afbbe0d 22198+ AuDebugOn(btop < *bcpup
5527c038 22199+ || au_test_ro(sb, *bcpup, d_inode(dentry)));
5afbbe0d 22200+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop);
1308ab2a 22201+
5afbbe0d 22202+ if (*bcpup != btop) {
4a4d8108
AM
22203+ err = au_cpup_dirs(dentry, *bcpup);
22204+ if (unlikely(err))
22205+ goto out;
22206+ need_wh = 1;
22207+ } else {
027c5e7a 22208+ struct au_dinfo *dinfo, *tmp;
4a4d8108 22209+
027c5e7a
AM
22210+ need_wh = -ENOMEM;
22211+ dinfo = au_di(dentry);
22212+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
22213+ if (tmp) {
22214+ au_di_cp(tmp, dinfo);
22215+ au_di_swap(tmp, dinfo);
22216+ /* returns the number of positive dentries */
5afbbe0d
AM
22217+ need_wh = au_lkup_dentry(dentry, btop + 1,
22218+ /* AuLkup_IGNORE_PERM */ 0);
027c5e7a
AM
22219+ au_di_swap(tmp, dinfo);
22220+ au_rw_write_unlock(&tmp->di_rwsem);
22221+ au_di_free(tmp);
4a4d8108
AM
22222+ }
22223+ }
22224+ AuDbg("need_wh %d\n", need_wh);
22225+ err = need_wh;
22226+
4f0767ce 22227+out:
4a4d8108 22228+ return err;
1facf9fc 22229+}
22230+
4a4d8108
AM
22231+/*
22232+ * simple tests for the del-entry operations.
22233+ * following the checks in vfs, plus the parent-child relationship.
22234+ */
22235+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
22236+ struct dentry *h_parent, int isdir)
1facf9fc 22237+{
4a4d8108
AM
22238+ int err;
22239+ umode_t h_mode;
22240+ struct dentry *h_dentry, *h_latest;
1308ab2a 22241+ struct inode *h_inode;
1facf9fc 22242+
4a4d8108 22243+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 22244+ if (d_really_is_positive(dentry)) {
4a4d8108 22245+ err = -ENOENT;
5527c038
JR
22246+ if (unlikely(d_is_negative(h_dentry)))
22247+ goto out;
22248+ h_inode = d_inode(h_dentry);
22249+ if (unlikely(!h_inode->i_nlink))
4a4d8108 22250+ goto out;
1facf9fc 22251+
4a4d8108
AM
22252+ h_mode = h_inode->i_mode;
22253+ if (!isdir) {
22254+ err = -EISDIR;
22255+ if (unlikely(S_ISDIR(h_mode)))
22256+ goto out;
22257+ } else if (unlikely(!S_ISDIR(h_mode))) {
22258+ err = -ENOTDIR;
22259+ goto out;
22260+ }
22261+ } else {
22262+ /* rename(2) case */
22263+ err = -EIO;
5527c038 22264+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
22265+ goto out;
22266+ }
1facf9fc 22267+
4a4d8108
AM
22268+ err = -ENOENT;
22269+ /* expected parent dir is locked */
22270+ if (unlikely(h_parent != h_dentry->d_parent))
22271+ goto out;
22272+ err = 0;
22273+
22274+ /*
22275+ * rmdir a dir may break the consistency on some filesystem.
22276+ * let's try heavy test.
22277+ */
22278+ err = -EACCES;
076b876e 22279+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
5527c038 22280+ && au_test_h_perm(d_inode(h_parent),
076b876e 22281+ MAY_EXEC | MAY_WRITE)))
4a4d8108
AM
22282+ goto out;
22283+
076b876e 22284+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent);
4a4d8108
AM
22285+ err = -EIO;
22286+ if (IS_ERR(h_latest))
22287+ goto out;
22288+ if (h_latest == h_dentry)
22289+ err = 0;
22290+ dput(h_latest);
22291+
4f0767ce 22292+out:
4a4d8108 22293+ return err;
1308ab2a 22294+}
1facf9fc 22295+
4a4d8108
AM
22296+/*
22297+ * decide the branch where we operate for @dentry. the branch index will be set
acd2b654 22298+ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent
4a4d8108
AM
22299+ * dir for reverting.
22300+ * when a new whiteout is necessary, create it.
22301+ */
22302+static struct dentry*
22303+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
22304+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 22305+{
4a4d8108
AM
22306+ struct dentry *wh_dentry;
22307+ struct super_block *sb;
22308+ struct path h_path;
22309+ int err, need_wh;
22310+ unsigned int udba;
22311+ aufs_bindex_t bcpup;
dece6358 22312+
4a4d8108
AM
22313+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
22314+ wh_dentry = ERR_PTR(need_wh);
22315+ if (unlikely(need_wh < 0))
22316+ goto out;
22317+
22318+ sb = dentry->d_sb;
22319+ udba = au_opt_udba(sb);
22320+ bcpup = *rbcpup;
22321+ err = au_pin(pin, dentry, bcpup, udba,
22322+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
22323+ wh_dentry = ERR_PTR(err);
22324+ if (unlikely(err))
22325+ goto out;
22326+
22327+ h_path.dentry = au_pinned_h_parent(pin);
22328+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 22329+ && au_dbtop(dentry) == bcpup) {
4a4d8108
AM
22330+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
22331+ wh_dentry = ERR_PTR(err);
22332+ if (unlikely(err))
22333+ goto out_unpin;
22334+ }
22335+
22336+ h_path.mnt = au_sbr_mnt(sb, bcpup);
22337+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
22338+ wh_dentry = NULL;
22339+ if (!need_wh)
22340+ goto out; /* success, no need to create whiteout */
22341+
22342+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
22343+ if (IS_ERR(wh_dentry))
22344+ goto out_unpin;
22345+
22346+ /* returns with the parent is locked and wh_dentry is dget-ed */
22347+ goto out; /* success */
22348+
4f0767ce 22349+out_unpin:
4a4d8108 22350+ au_unpin(pin);
4f0767ce 22351+out:
4a4d8108 22352+ return wh_dentry;
1facf9fc 22353+}
22354+
4a4d8108
AM
22355+/*
22356+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
22357+ * in order to be revertible and save time for removing many child whiteouts
22358+ * under the dir.
22359+ * returns 1 when there are too many child whiteout and caller should remove
22360+ * them asynchronously. returns 0 when the number of children is enough small to
22361+ * remove now or the branch fs is a remote fs.
22362+ * otherwise return an error.
22363+ */
22364+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
22365+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 22366+{
4a4d8108
AM
22367+ int rmdir_later, err, dirwh;
22368+ struct dentry *h_dentry;
22369+ struct super_block *sb;
5527c038 22370+ struct inode *inode;
4a4d8108
AM
22371+
22372+ sb = dentry->d_sb;
22373+ SiMustAnyLock(sb);
22374+ h_dentry = au_h_dptr(dentry, bindex);
22375+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
22376+ if (unlikely(err))
22377+ goto out;
22378+
22379+ /* stop monitoring */
5527c038
JR
22380+ inode = d_inode(dentry);
22381+ au_hn_free(au_hi(inode, bindex));
4a4d8108
AM
22382+
22383+ if (!au_test_fs_remote(h_dentry->d_sb)) {
22384+ dirwh = au_sbi(sb)->si_dirwh;
22385+ rmdir_later = (dirwh <= 1);
22386+ if (!rmdir_later)
22387+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
22388+ dirwh);
22389+ if (rmdir_later)
22390+ return rmdir_later;
22391+ }
1facf9fc 22392+
4a4d8108
AM
22393+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
22394+ if (unlikely(err)) {
523b37e3
AM
22395+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n",
22396+ h_dentry, bindex, err);
4a4d8108
AM
22397+ err = 0;
22398+ }
dece6358 22399+
4f0767ce 22400+out:
4a4d8108
AM
22401+ AuTraceErr(err);
22402+ return err;
22403+}
1308ab2a 22404+
4a4d8108
AM
22405+/*
22406+ * final procedure for deleting a entry.
22407+ * maintain dentry and iattr.
22408+ */
22409+static void epilog(struct inode *dir, struct dentry *dentry,
22410+ aufs_bindex_t bindex)
22411+{
22412+ struct inode *inode;
1308ab2a 22413+
5527c038 22414+ inode = d_inode(dentry);
4a4d8108
AM
22415+ d_drop(dentry);
22416+ inode->i_ctime = dir->i_ctime;
1308ab2a 22417+
b912730e 22418+ au_dir_ts(dir, bindex);
be118d29 22419+ inode_inc_iversion(dir);
1facf9fc 22420+}
22421+
4a4d8108
AM
22422+/*
22423+ * when an error happened, remove the created whiteout and revert everything.
22424+ */
7f207e10
AM
22425+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
22426+ aufs_bindex_t bwh, struct dentry *wh_dentry,
22427+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 22428+{
4a4d8108
AM
22429+ int rerr;
22430+ struct path h_path = {
22431+ .dentry = wh_dentry,
7f207e10 22432+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 22433+ };
dece6358 22434+
7f207e10 22435+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
22436+ if (!rerr) {
22437+ au_set_dbwh(dentry, bwh);
22438+ au_dtime_revert(dt);
22439+ return 0;
22440+ }
dece6358 22441+
523b37e3 22442+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr);
4a4d8108 22443+ return -EIO;
1facf9fc 22444+}
22445+
4a4d8108 22446+/* ---------------------------------------------------------------------- */
1facf9fc 22447+
4a4d8108 22448+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 22449+{
4a4d8108 22450+ int err;
5afbbe0d 22451+ aufs_bindex_t bwh, bindex, btop;
523b37e3 22452+ struct inode *inode, *h_dir, *delegated;
4a4d8108 22453+ struct dentry *parent, *wh_dentry;
acd2b654 22454+ /* to reduce stack size */
c2b27bf2
AM
22455+ struct {
22456+ struct au_dtime dt;
22457+ struct au_pin pin;
22458+ struct path h_path;
22459+ } *a;
1facf9fc 22460+
4a4d8108 22461+ IMustLock(dir);
027c5e7a 22462+
c2b27bf2
AM
22463+ err = -ENOMEM;
22464+ a = kmalloc(sizeof(*a), GFP_NOFS);
22465+ if (unlikely(!a))
22466+ goto out;
22467+
027c5e7a
AM
22468+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
22469+ if (unlikely(err))
c2b27bf2 22470+ goto out_free;
027c5e7a
AM
22471+ err = au_d_hashed_positive(dentry);
22472+ if (unlikely(err))
22473+ goto out_unlock;
5527c038 22474+ inode = d_inode(dentry);
4a4d8108 22475+ IMustLock(inode);
027c5e7a 22476+ err = -EISDIR;
2000de60 22477+ if (unlikely(d_is_dir(dentry)))
027c5e7a 22478+ goto out_unlock; /* possible? */
1facf9fc 22479+
5afbbe0d 22480+ btop = au_dbtop(dentry);
4a4d8108
AM
22481+ bwh = au_dbwh(dentry);
22482+ bindex = -1;
027c5e7a
AM
22483+ parent = dentry->d_parent; /* dir inode is locked */
22484+ di_write_lock_parent(parent);
c2b27bf2
AM
22485+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
22486+ &a->pin);
4a4d8108
AM
22487+ err = PTR_ERR(wh_dentry);
22488+ if (IS_ERR(wh_dentry))
027c5e7a 22489+ goto out_parent;
1facf9fc 22490+
5afbbe0d
AM
22491+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop);
22492+ a->h_path.dentry = au_h_dptr(dentry, btop);
c2b27bf2 22493+ dget(a->h_path.dentry);
5afbbe0d 22494+ if (bindex == btop) {
c2b27bf2 22495+ h_dir = au_pinned_h_dir(&a->pin);
523b37e3
AM
22496+ delegated = NULL;
22497+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0);
22498+ if (unlikely(err == -EWOULDBLOCK)) {
22499+ pr_warn("cannot retry for NFSv4 delegation"
22500+ " for an internal unlink\n");
22501+ iput(delegated);
22502+ }
4a4d8108
AM
22503+ } else {
22504+ /* dir inode is locked */
5527c038 22505+ h_dir = d_inode(wh_dentry->d_parent);
4a4d8108
AM
22506+ IMustLock(h_dir);
22507+ err = 0;
22508+ }
dece6358 22509+
4a4d8108 22510+ if (!err) {
7f207e10 22511+ vfsub_drop_nlink(inode);
4a4d8108
AM
22512+ epilog(dir, dentry, bindex);
22513+
22514+ /* update target timestamps */
5afbbe0d 22515+ if (bindex == btop) {
c2b27bf2
AM
22516+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
22517+ /*ignore*/
5527c038 22518+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
4a4d8108
AM
22519+ } else
22520+ /* todo: this timestamp may be reverted later */
22521+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 22522+ goto out_unpin; /* success */
1facf9fc 22523+ }
22524+
4a4d8108
AM
22525+ /* revert */
22526+ if (wh_dentry) {
22527+ int rerr;
22528+
c2b27bf2
AM
22529+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22530+ &a->dt);
4a4d8108
AM
22531+ if (rerr)
22532+ err = rerr;
dece6358 22533+ }
1facf9fc 22534+
027c5e7a 22535+out_unpin:
c2b27bf2 22536+ au_unpin(&a->pin);
4a4d8108 22537+ dput(wh_dentry);
c2b27bf2 22538+ dput(a->h_path.dentry);
027c5e7a 22539+out_parent:
4a4d8108 22540+ di_write_unlock(parent);
027c5e7a 22541+out_unlock:
4a4d8108 22542+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22543+out_free:
9f237c51 22544+ au_kfree_rcu(a);
027c5e7a 22545+out:
4a4d8108 22546+ return err;
dece6358
AM
22547+}
22548+
4a4d8108 22549+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 22550+{
4a4d8108 22551+ int err, rmdir_later;
5afbbe0d 22552+ aufs_bindex_t bwh, bindex, btop;
4a4d8108
AM
22553+ struct inode *inode;
22554+ struct dentry *parent, *wh_dentry, *h_dentry;
22555+ struct au_whtmp_rmdir *args;
acd2b654 22556+ /* to reduce stack size */
c2b27bf2
AM
22557+ struct {
22558+ struct au_dtime dt;
22559+ struct au_pin pin;
22560+ } *a;
1facf9fc 22561+
4a4d8108 22562+ IMustLock(dir);
027c5e7a 22563+
c2b27bf2
AM
22564+ err = -ENOMEM;
22565+ a = kmalloc(sizeof(*a), GFP_NOFS);
22566+ if (unlikely(!a))
22567+ goto out;
22568+
027c5e7a
AM
22569+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
22570+ if (unlikely(err))
c2b27bf2 22571+ goto out_free;
53392da6
AM
22572+ err = au_alive_dir(dentry);
22573+ if (unlikely(err))
027c5e7a 22574+ goto out_unlock;
5527c038 22575+ inode = d_inode(dentry);
4a4d8108 22576+ IMustLock(inode);
027c5e7a 22577+ err = -ENOTDIR;
2000de60 22578+ if (unlikely(!d_is_dir(dentry)))
027c5e7a 22579+ goto out_unlock; /* possible? */
dece6358 22580+
4a4d8108
AM
22581+ err = -ENOMEM;
22582+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
22583+ if (unlikely(!args))
22584+ goto out_unlock;
dece6358 22585+
4a4d8108
AM
22586+ parent = dentry->d_parent; /* dir inode is locked */
22587+ di_write_lock_parent(parent);
22588+ err = au_test_empty(dentry, &args->whlist);
22589+ if (unlikely(err))
027c5e7a 22590+ goto out_parent;
1facf9fc 22591+
5afbbe0d 22592+ btop = au_dbtop(dentry);
4a4d8108
AM
22593+ bwh = au_dbwh(dentry);
22594+ bindex = -1;
c2b27bf2
AM
22595+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
22596+ &a->pin);
4a4d8108
AM
22597+ err = PTR_ERR(wh_dentry);
22598+ if (IS_ERR(wh_dentry))
027c5e7a 22599+ goto out_parent;
1facf9fc 22600+
5afbbe0d 22601+ h_dentry = au_h_dptr(dentry, btop);
4a4d8108
AM
22602+ dget(h_dentry);
22603+ rmdir_later = 0;
5afbbe0d
AM
22604+ if (bindex == btop) {
22605+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir);
4a4d8108
AM
22606+ if (err > 0) {
22607+ rmdir_later = err;
22608+ err = 0;
22609+ }
22610+ } else {
22611+ /* stop monitoring */
5afbbe0d 22612+ au_hn_free(au_hi(inode, btop));
4a4d8108
AM
22613+
22614+ /* dir inode is locked */
5527c038 22615+ IMustLock(d_inode(wh_dentry->d_parent));
1facf9fc 22616+ err = 0;
22617+ }
22618+
4a4d8108 22619+ if (!err) {
027c5e7a 22620+ vfsub_dead_dir(inode);
4a4d8108
AM
22621+ au_set_dbdiropq(dentry, -1);
22622+ epilog(dir, dentry, bindex);
1308ab2a 22623+
4a4d8108 22624+ if (rmdir_later) {
5afbbe0d 22625+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args);
4a4d8108
AM
22626+ args = NULL;
22627+ }
1308ab2a 22628+
4a4d8108 22629+ goto out_unpin; /* success */
1facf9fc 22630+ }
22631+
4a4d8108
AM
22632+ /* revert */
22633+ AuLabel(revert);
22634+ if (wh_dentry) {
22635+ int rerr;
1308ab2a 22636+
c2b27bf2
AM
22637+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22638+ &a->dt);
4a4d8108
AM
22639+ if (rerr)
22640+ err = rerr;
1facf9fc 22641+ }
22642+
4f0767ce 22643+out_unpin:
c2b27bf2 22644+ au_unpin(&a->pin);
4a4d8108
AM
22645+ dput(wh_dentry);
22646+ dput(h_dentry);
027c5e7a 22647+out_parent:
4a4d8108
AM
22648+ di_write_unlock(parent);
22649+ if (args)
22650+ au_whtmp_rmdir_free(args);
4f0767ce 22651+out_unlock:
4a4d8108 22652+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22653+out_free:
9f237c51 22654+ au_kfree_rcu(a);
4f0767ce 22655+out:
4a4d8108
AM
22656+ AuTraceErr(err);
22657+ return err;
dece6358 22658+}
7f207e10 22659diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
eca34b5c
AM
22660--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
22661+++ linux/fs/aufs/i_op_ren.c 2019-07-11 15:42:14.468904634 +0200
eca801bf 22662@@ -0,0 +1,1250 @@
cd7a4cd9 22663+// SPDX-License-Identifier: GPL-2.0
1facf9fc 22664+/*
ba1aed25 22665+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 22666+ *
22667+ * This program, aufs is free software; you can redistribute it and/or modify
22668+ * it under the terms of the GNU General Public License as published by
22669+ * the Free Software Foundation; either version 2 of the License, or
22670+ * (at your option) any later version.
dece6358
AM
22671+ *
22672+ * This program is distributed in the hope that it will be useful,
22673+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22674+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22675+ * GNU General Public License for more details.
22676+ *
22677+ * You should have received a copy of the GNU General Public License
523b37e3 22678+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22679+ */
22680+
22681+/*
4a4d8108
AM
22682+ * inode operation (rename entry)
22683+ * todo: this is crazy monster
1facf9fc 22684+ */
22685+
eca801bf 22686+#include <linux/iversion.h>
1facf9fc 22687+#include "aufs.h"
22688+
4a4d8108
AM
22689+enum { AuSRC, AuDST, AuSrcDst };
22690+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 22691+
f2c43d5f
AM
22692+#define AuRen_ISDIR_SRC 1
22693+#define AuRen_ISDIR_DST (1 << 1)
22694+#define AuRen_ISSAMEDIR (1 << 2)
22695+#define AuRen_WHSRC (1 << 3)
22696+#define AuRen_WHDST (1 << 4)
22697+#define AuRen_MNT_WRITE (1 << 5)
22698+#define AuRen_DT_DSTDIR (1 << 6)
22699+#define AuRen_DIROPQ_SRC (1 << 7)
22700+#define AuRen_DIROPQ_DST (1 << 8)
8b6a4947
AM
22701+#define AuRen_DIRREN (1 << 9)
22702+#define AuRen_DROPPED_SRC (1 << 10)
22703+#define AuRen_DROPPED_DST (1 << 11)
4a4d8108 22704+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
22705+#define au_fset_ren(flags, name) \
22706+ do { (flags) |= AuRen_##name; } while (0)
22707+#define au_fclr_ren(flags, name) \
22708+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 22709+
8b6a4947
AM
22710+#ifndef CONFIG_AUFS_DIRREN
22711+#undef AuRen_DIRREN
22712+#define AuRen_DIRREN 0
22713+#endif
22714+
4a4d8108
AM
22715+struct au_ren_args {
22716+ struct {
22717+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
22718+ *wh_dentry;
22719+ struct inode *dir, *inode;
f2c43d5f 22720+ struct au_hinode *hdir, *hinode;
4a4d8108 22721+ struct au_dtime dt[AuParentChild];
f2c43d5f 22722+ aufs_bindex_t btop, bdiropq;
4a4d8108 22723+ } sd[AuSrcDst];
1facf9fc 22724+
4a4d8108
AM
22725+#define src_dentry sd[AuSRC].dentry
22726+#define src_dir sd[AuSRC].dir
22727+#define src_inode sd[AuSRC].inode
22728+#define src_h_dentry sd[AuSRC].h_dentry
22729+#define src_parent sd[AuSRC].parent
22730+#define src_h_parent sd[AuSRC].h_parent
22731+#define src_wh_dentry sd[AuSRC].wh_dentry
22732+#define src_hdir sd[AuSRC].hdir
f2c43d5f 22733+#define src_hinode sd[AuSRC].hinode
4a4d8108
AM
22734+#define src_h_dir sd[AuSRC].hdir->hi_inode
22735+#define src_dt sd[AuSRC].dt
5afbbe0d 22736+#define src_btop sd[AuSRC].btop
f2c43d5f 22737+#define src_bdiropq sd[AuSRC].bdiropq
1facf9fc 22738+
4a4d8108
AM
22739+#define dst_dentry sd[AuDST].dentry
22740+#define dst_dir sd[AuDST].dir
22741+#define dst_inode sd[AuDST].inode
22742+#define dst_h_dentry sd[AuDST].h_dentry
22743+#define dst_parent sd[AuDST].parent
22744+#define dst_h_parent sd[AuDST].h_parent
22745+#define dst_wh_dentry sd[AuDST].wh_dentry
22746+#define dst_hdir sd[AuDST].hdir
f2c43d5f 22747+#define dst_hinode sd[AuDST].hinode
4a4d8108
AM
22748+#define dst_h_dir sd[AuDST].hdir->hi_inode
22749+#define dst_dt sd[AuDST].dt
5afbbe0d 22750+#define dst_btop sd[AuDST].btop
f2c43d5f 22751+#define dst_bdiropq sd[AuDST].bdiropq
4a4d8108
AM
22752+
22753+ struct dentry *h_trap;
22754+ struct au_branch *br;
4a4d8108
AM
22755+ struct path h_path;
22756+ struct au_nhash whlist;
f2c43d5f 22757+ aufs_bindex_t btgt, src_bwh;
1facf9fc 22758+
f2c43d5f
AM
22759+ struct {
22760+ unsigned short auren_flags;
22761+ unsigned char flags; /* syscall parameter */
22762+ unsigned char exchange;
22763+ } __packed;
1facf9fc 22764+
4a4d8108
AM
22765+ struct au_whtmp_rmdir *thargs;
22766+ struct dentry *h_dst;
8b6a4947 22767+ struct au_hinode *h_root;
4a4d8108 22768+};
1308ab2a 22769+
4a4d8108 22770+/* ---------------------------------------------------------------------- */
1308ab2a 22771+
4a4d8108
AM
22772+/*
22773+ * functions for reverting.
22774+ * when an error happened in a single rename systemcall, we should revert
79b8bda9 22775+ * everything as if nothing happened.
4a4d8108
AM
22776+ * we don't need to revert the copied-up/down the parent dir since they are
22777+ * harmless.
22778+ */
1facf9fc 22779+
4a4d8108
AM
22780+#define RevertFailure(fmt, ...) do { \
22781+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
22782+ ##__VA_ARGS__, err, rerr); \
22783+ err = -EIO; \
22784+} while (0)
1facf9fc 22785+
f2c43d5f 22786+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx)
1facf9fc 22787+{
4a4d8108 22788+ int rerr;
f2c43d5f
AM
22789+ struct dentry *d;
22790+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22791+
f2c43d5f
AM
22792+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22793+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22794+ rerr = au_diropq_remove(d, a->btgt);
22795+ au_hn_inode_unlock(src_or_dst(hinode));
22796+ au_set_dbdiropq(d, src_or_dst(bdiropq));
4a4d8108 22797+ if (rerr)
f2c43d5f
AM
22798+ RevertFailure("remove diropq %pd", d);
22799+
22800+#undef src_or_dst_
22801+}
22802+
22803+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
22804+{
22805+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC))
22806+ au_ren_do_rev_diropq(err, a, AuSRC);
22807+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST))
22808+ au_ren_do_rev_diropq(err, a, AuDST);
4a4d8108 22809+}
1facf9fc 22810+
4a4d8108
AM
22811+static void au_ren_rev_rename(int err, struct au_ren_args *a)
22812+{
22813+ int rerr;
523b37e3 22814+ struct inode *delegated;
1facf9fc 22815+
b4510431
AM
22816+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
22817+ a->src_h_parent);
4a4d8108
AM
22818+ rerr = PTR_ERR(a->h_path.dentry);
22819+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22820+ RevertFailure("lkup one %pd", a->src_dentry);
4a4d8108 22821+ return;
1facf9fc 22822+ }
22823+
523b37e3 22824+ delegated = NULL;
4a4d8108
AM
22825+ rerr = vfsub_rename(a->dst_h_dir,
22826+ au_h_dptr(a->src_dentry, a->btgt),
f2c43d5f 22827+ a->src_h_dir, &a->h_path, &delegated, a->flags);
523b37e3
AM
22828+ if (unlikely(rerr == -EWOULDBLOCK)) {
22829+ pr_warn("cannot retry for NFSv4 delegation"
22830+ " for an internal rename\n");
22831+ iput(delegated);
22832+ }
4a4d8108
AM
22833+ d_drop(a->h_path.dentry);
22834+ dput(a->h_path.dentry);
22835+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
22836+ if (rerr)
523b37e3 22837+ RevertFailure("rename %pd", a->src_dentry);
1facf9fc 22838+}
22839+
4a4d8108 22840+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 22841+{
4a4d8108 22842+ int rerr;
523b37e3 22843+ struct inode *delegated;
dece6358 22844+
b4510431
AM
22845+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
22846+ a->dst_h_parent);
4a4d8108
AM
22847+ rerr = PTR_ERR(a->h_path.dentry);
22848+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22849+ RevertFailure("lkup one %pd", a->dst_dentry);
4a4d8108
AM
22850+ return;
22851+ }
5527c038 22852+ if (d_is_positive(a->h_path.dentry)) {
4a4d8108
AM
22853+ d_drop(a->h_path.dentry);
22854+ dput(a->h_path.dentry);
22855+ return;
dece6358
AM
22856+ }
22857+
523b37e3
AM
22858+ delegated = NULL;
22859+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path,
f2c43d5f 22860+ &delegated, a->flags);
523b37e3
AM
22861+ if (unlikely(rerr == -EWOULDBLOCK)) {
22862+ pr_warn("cannot retry for NFSv4 delegation"
22863+ " for an internal rename\n");
22864+ iput(delegated);
22865+ }
4a4d8108
AM
22866+ d_drop(a->h_path.dentry);
22867+ dput(a->h_path.dentry);
22868+ if (!rerr)
22869+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
22870+ else
523b37e3 22871+ RevertFailure("rename %pd", a->h_dst);
4a4d8108 22872+}
1308ab2a 22873+
4a4d8108
AM
22874+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
22875+{
22876+ int rerr;
1308ab2a 22877+
4a4d8108
AM
22878+ a->h_path.dentry = a->src_wh_dentry;
22879+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 22880+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108 22881+ if (rerr)
523b37e3 22882+ RevertFailure("unlink %pd", a->src_wh_dentry);
4a4d8108 22883+}
4a4d8108 22884+#undef RevertFailure
1facf9fc 22885+
1308ab2a 22886+/* ---------------------------------------------------------------------- */
22887+
4a4d8108
AM
22888+/*
22889+ * when we have to copyup the renaming entry, do it with the rename-target name
22890+ * in order to minimize the cost (the later actual rename is unnecessary).
22891+ * otherwise rename it on the target branch.
22892+ */
22893+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 22894+{
dece6358 22895+ int err;
4a4d8108 22896+ struct dentry *d;
523b37e3 22897+ struct inode *delegated;
1facf9fc 22898+
4a4d8108 22899+ d = a->src_dentry;
5afbbe0d 22900+ if (au_dbtop(d) == a->btgt) {
4a4d8108 22901+ a->h_path.dentry = a->dst_h_dentry;
5afbbe0d 22902+ AuDebugOn(au_dbtop(d) != a->btgt);
523b37e3 22903+ delegated = NULL;
4a4d8108 22904+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
f2c43d5f
AM
22905+ a->dst_h_dir, &a->h_path, &delegated,
22906+ a->flags);
523b37e3
AM
22907+ if (unlikely(err == -EWOULDBLOCK)) {
22908+ pr_warn("cannot retry for NFSv4 delegation"
22909+ " for an internal rename\n");
22910+ iput(delegated);
22911+ }
c2b27bf2 22912+ } else
86dc4139 22913+ BUG();
1308ab2a 22914+
027c5e7a
AM
22915+ if (!err && a->h_dst)
22916+ /* it will be set to dinfo later */
22917+ dget(a->h_dst);
1facf9fc 22918+
dece6358
AM
22919+ return err;
22920+}
1facf9fc 22921+
4a4d8108
AM
22922+/* cf. aufs_rmdir() */
22923+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 22924+{
4a4d8108
AM
22925+ int err;
22926+ struct inode *dir;
1facf9fc 22927+
4a4d8108
AM
22928+ dir = a->dst_dir;
22929+ SiMustAnyLock(dir->i_sb);
22930+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
22931+ au_sbi(dir->i_sb)->si_dirwh)
22932+ || au_test_fs_remote(a->h_dst->d_sb)) {
22933+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
22934+ if (unlikely(err))
523b37e3
AM
22935+ pr_warn("failed removing whtmp dir %pd (%d), "
22936+ "ignored.\n", a->h_dst, err);
4a4d8108
AM
22937+ } else {
22938+ au_nhash_wh_free(&a->thargs->whlist);
22939+ a->thargs->whlist = a->whlist;
22940+ a->whlist.nh_num = 0;
22941+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
22942+ dput(a->h_dst);
22943+ a->thargs = NULL;
22944+ }
22945+
22946+ return 0;
1308ab2a 22947+}
1facf9fc 22948+
4a4d8108 22949+/* make it 'opaque' dir. */
f2c43d5f 22950+static int au_ren_do_diropq(struct au_ren_args *a, int idx)
4a4d8108
AM
22951+{
22952+ int err;
f2c43d5f
AM
22953+ struct dentry *d, *diropq;
22954+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22955+
4a4d8108 22956+ err = 0;
f2c43d5f
AM
22957+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22958+ src_or_dst(bdiropq) = au_dbdiropq(d);
22959+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt);
22960+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22961+ diropq = au_diropq_create(d, a->btgt);
22962+ au_hn_inode_unlock(src_or_dst(hinode));
4a4d8108
AM
22963+ if (IS_ERR(diropq))
22964+ err = PTR_ERR(diropq);
076b876e
AM
22965+ else
22966+ dput(diropq);
1facf9fc 22967+
f2c43d5f 22968+#undef src_or_dst_
4a4d8108
AM
22969+ return err;
22970+}
1facf9fc 22971+
f2c43d5f 22972+static int au_ren_diropq(struct au_ren_args *a)
4a4d8108
AM
22973+{
22974+ int err;
f2c43d5f
AM
22975+ unsigned char always;
22976+ struct dentry *d;
1facf9fc 22977+
f2c43d5f
AM
22978+ err = 0;
22979+ d = a->dst_dentry; /* already renamed on the branch */
22980+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ);
22981+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
8b6a4947 22982+ && !au_ftest_ren(a->auren_flags, DIRREN)
f2c43d5f
AM
22983+ && a->btgt != au_dbdiropq(a->src_dentry)
22984+ && (a->dst_wh_dentry
22985+ || a->btgt <= au_dbdiropq(d)
22986+ /* hide the lower to keep xino */
22987+ /* the lowers may not be a dir, but we hide them anyway */
22988+ || a->btgt < au_dbbot(d)
22989+ || always)) {
22990+ AuDbg("here\n");
22991+ err = au_ren_do_diropq(a, AuSRC);
22992+ if (unlikely(err))
4a4d8108 22993+ goto out;
f2c43d5f 22994+ au_fset_ren(a->auren_flags, DIROPQ_SRC);
4a4d8108 22995+ }
f2c43d5f
AM
22996+ if (!a->exchange)
22997+ goto out; /* success */
1facf9fc 22998+
f2c43d5f
AM
22999+ d = a->src_dentry; /* already renamed on the branch */
23000+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
23001+ && a->btgt != au_dbdiropq(a->dst_dentry)
23002+ && (a->btgt < au_dbdiropq(d)
23003+ || a->btgt < au_dbbot(d)
23004+ || always)) {
23005+ AuDbgDentry(a->src_dentry);
23006+ AuDbgDentry(a->dst_dentry);
23007+ err = au_ren_do_diropq(a, AuDST);
4a4d8108 23008+ if (unlikely(err))
f2c43d5f
AM
23009+ goto out_rev_src;
23010+ au_fset_ren(a->auren_flags, DIROPQ_DST);
23011+ }
23012+ goto out; /* success */
dece6358 23013+
f2c43d5f
AM
23014+out_rev_src:
23015+ AuDbg("err %d, reverting src\n", err);
23016+ au_ren_rev_diropq(err, a);
23017+out:
23018+ return err;
23019+}
23020+
23021+static int do_rename(struct au_ren_args *a)
23022+{
23023+ int err;
23024+ struct dentry *d, *h_d;
23025+
23026+ if (!a->exchange) {
23027+ /* prepare workqueue args for asynchronous rmdir */
23028+ h_d = a->dst_h_dentry;
23029+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
8b6a4947 23030+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */
f2c43d5f
AM
23031+ && d_is_positive(h_d)) {
23032+ err = -ENOMEM;
23033+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb,
23034+ GFP_NOFS);
23035+ if (unlikely(!a->thargs))
23036+ goto out;
23037+ a->h_dst = dget(h_d);
23038+ }
23039+
23040+ /* create whiteout for src_dentry */
23041+ if (au_ftest_ren(a->auren_flags, WHSRC)) {
23042+ a->src_bwh = au_dbwh(a->src_dentry);
23043+ AuDebugOn(a->src_bwh >= 0);
23044+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt,
23045+ a->src_h_parent);
23046+ err = PTR_ERR(a->src_wh_dentry);
23047+ if (IS_ERR(a->src_wh_dentry))
23048+ goto out_thargs;
23049+ }
23050+
23051+ /* lookup whiteout for dentry */
23052+ if (au_ftest_ren(a->auren_flags, WHDST)) {
23053+ h_d = au_wh_lkup(a->dst_h_parent,
23054+ &a->dst_dentry->d_name, a->br);
23055+ err = PTR_ERR(h_d);
23056+ if (IS_ERR(h_d))
23057+ goto out_whsrc;
23058+ if (d_is_negative(h_d))
23059+ dput(h_d);
23060+ else
23061+ a->dst_wh_dentry = h_d;
23062+ }
23063+
23064+ /* rename dentry to tmpwh */
23065+ if (a->thargs) {
23066+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
23067+ if (unlikely(err))
23068+ goto out_whdst;
23069+
23070+ d = a->dst_dentry;
23071+ au_set_h_dptr(d, a->btgt, NULL);
23072+ err = au_lkup_neg(d, a->btgt, /*wh*/0);
23073+ if (unlikely(err))
23074+ goto out_whtmp;
23075+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
23076+ }
4a4d8108 23077+ }
1facf9fc 23078+
5afbbe0d 23079+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt);
8b6a4947
AM
23080+#if 0
23081+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN)
23082+ && d_is_positive(a->dst_h_dentry)
23083+ && a->src_btop != a->btgt);
23084+#endif
1facf9fc 23085+
4a4d8108 23086+ /* rename by vfs_rename or cpup */
4a4d8108
AM
23087+ err = au_ren_or_cpup(a);
23088+ if (unlikely(err))
23089+ /* leave the copied-up one */
23090+ goto out_whtmp;
1308ab2a 23091+
4a4d8108 23092+ /* make dir opaque */
f2c43d5f
AM
23093+ err = au_ren_diropq(a);
23094+ if (unlikely(err))
23095+ goto out_rename;
1308ab2a 23096+
4a4d8108 23097+ /* update target timestamps */
f2c43d5f
AM
23098+ if (a->exchange) {
23099+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt);
23100+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt);
23101+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
23102+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
23103+ }
5afbbe0d 23104+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt);
4a4d8108
AM
23105+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
23106+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
5527c038 23107+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
1facf9fc 23108+
f2c43d5f
AM
23109+ if (!a->exchange) {
23110+ /* remove whiteout for dentry */
23111+ if (a->dst_wh_dentry) {
23112+ a->h_path.dentry = a->dst_wh_dentry;
23113+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
23114+ a->dst_dentry);
23115+ if (unlikely(err))
23116+ goto out_diropq;
23117+ }
1facf9fc 23118+
f2c43d5f
AM
23119+ /* remove whtmp */
23120+ if (a->thargs)
23121+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 23122+
f2c43d5f
AM
23123+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0);
23124+ }
4a4d8108
AM
23125+ err = 0;
23126+ goto out_success;
23127+
4f0767ce 23128+out_diropq:
f2c43d5f 23129+ au_ren_rev_diropq(err, a);
4f0767ce 23130+out_rename:
7e9cd9fe 23131+ au_ren_rev_rename(err, a);
027c5e7a 23132+ dput(a->h_dst);
4f0767ce 23133+out_whtmp:
4a4d8108
AM
23134+ if (a->thargs)
23135+ au_ren_rev_whtmp(err, a);
4f0767ce 23136+out_whdst:
4a4d8108
AM
23137+ dput(a->dst_wh_dentry);
23138+ a->dst_wh_dentry = NULL;
4f0767ce 23139+out_whsrc:
4a4d8108
AM
23140+ if (a->src_wh_dentry)
23141+ au_ren_rev_whsrc(err, a);
4f0767ce 23142+out_success:
4a4d8108
AM
23143+ dput(a->src_wh_dentry);
23144+ dput(a->dst_wh_dentry);
4f0767ce 23145+out_thargs:
4a4d8108
AM
23146+ if (a->thargs) {
23147+ dput(a->h_dst);
23148+ au_whtmp_rmdir_free(a->thargs);
23149+ a->thargs = NULL;
23150+ }
4f0767ce 23151+out:
4a4d8108 23152+ return err;
dece6358 23153+}
1facf9fc 23154+
1308ab2a 23155+/* ---------------------------------------------------------------------- */
1facf9fc 23156+
4a4d8108
AM
23157+/*
23158+ * test if @dentry dir can be rename destination or not.
23159+ * success means, it is a logically empty dir.
23160+ */
23161+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 23162+{
4a4d8108 23163+ return au_test_empty(dentry, whlist);
1308ab2a 23164+}
1facf9fc 23165+
4a4d8108 23166+/*
8b6a4947
AM
23167+ * test if @a->src_dentry dir can be rename source or not.
23168+ * if it can, return 0.
4a4d8108
AM
23169+ * success means,
23170+ * - it is a logically empty dir.
23171+ * - or, it exists on writable branch and has no children including whiteouts
8b6a4947 23172+ * on the lower branch unless DIRREN is on.
4a4d8108 23173+ */
8b6a4947 23174+static int may_rename_srcdir(struct au_ren_args *a)
4a4d8108
AM
23175+{
23176+ int err;
23177+ unsigned int rdhash;
8b6a4947
AM
23178+ aufs_bindex_t btop, btgt;
23179+ struct dentry *dentry;
23180+ struct super_block *sb;
23181+ struct au_sbinfo *sbinfo;
1facf9fc 23182+
8b6a4947
AM
23183+ dentry = a->src_dentry;
23184+ sb = dentry->d_sb;
23185+ sbinfo = au_sbi(sb);
23186+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
23187+ au_fset_ren(a->auren_flags, DIRREN);
23188+
23189+ btgt = a->btgt;
5afbbe0d
AM
23190+ btop = au_dbtop(dentry);
23191+ if (btop != btgt) {
4a4d8108 23192+ struct au_nhash whlist;
dece6358 23193+
8b6a4947
AM
23194+ SiMustAnyLock(sb);
23195+ rdhash = sbinfo->si_rdhash;
4a4d8108
AM
23196+ if (!rdhash)
23197+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
23198+ dentry));
23199+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
23200+ if (unlikely(err))
23201+ goto out;
23202+ err = au_test_empty(dentry, &whlist);
23203+ au_nhash_wh_free(&whlist);
23204+ goto out;
23205+ }
dece6358 23206+
5afbbe0d 23207+ if (btop == au_dbtaildir(dentry))
4a4d8108 23208+ return 0; /* success */
dece6358 23209+
4a4d8108 23210+ err = au_test_empty_lower(dentry);
1facf9fc 23211+
4f0767ce 23212+out:
4a4d8108 23213+ if (err == -ENOTEMPTY) {
8b6a4947
AM
23214+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23215+ err = 0;
23216+ } else {
23217+ AuWarn1("renaming dir who has child(ren) on multiple "
23218+ "branches, is not supported\n");
23219+ err = -EXDEV;
23220+ }
4a4d8108
AM
23221+ }
23222+ return err;
23223+}
1308ab2a 23224+
4a4d8108
AM
23225+/* side effect: sets whlist and h_dentry */
23226+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 23227+{
4a4d8108
AM
23228+ int err;
23229+ unsigned int rdhash;
23230+ struct dentry *d;
1facf9fc 23231+
4a4d8108
AM
23232+ d = a->dst_dentry;
23233+ SiMustAnyLock(d->d_sb);
1facf9fc 23234+
4a4d8108 23235+ err = 0;
f2c43d5f 23236+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) {
4a4d8108
AM
23237+ rdhash = au_sbi(d->d_sb)->si_rdhash;
23238+ if (!rdhash)
23239+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
23240+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
23241+ if (unlikely(err))
23242+ goto out;
1308ab2a 23243+
f2c43d5f
AM
23244+ if (!a->exchange) {
23245+ au_set_dbtop(d, a->dst_btop);
23246+ err = may_rename_dstdir(d, &a->whlist);
23247+ au_set_dbtop(d, a->btgt);
23248+ } else
8b6a4947 23249+ err = may_rename_srcdir(a);
4a4d8108 23250+ }
5afbbe0d 23251+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d));
4a4d8108
AM
23252+ if (unlikely(err))
23253+ goto out;
23254+
23255+ d = a->src_dentry;
5afbbe0d 23256+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d));
f2c43d5f 23257+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
8b6a4947 23258+ err = may_rename_srcdir(a);
4a4d8108
AM
23259+ if (unlikely(err)) {
23260+ au_nhash_wh_free(&a->whlist);
23261+ a->whlist.nh_num = 0;
23262+ }
23263+ }
4f0767ce 23264+out:
4a4d8108 23265+ return err;
1facf9fc 23266+}
23267+
4a4d8108 23268+/* ---------------------------------------------------------------------- */
1facf9fc 23269+
4a4d8108
AM
23270+/*
23271+ * simple tests for rename.
23272+ * following the checks in vfs, plus the parent-child relationship.
23273+ */
23274+static int au_may_ren(struct au_ren_args *a)
23275+{
23276+ int err, isdir;
23277+ struct inode *h_inode;
1facf9fc 23278+
5afbbe0d 23279+ if (a->src_btop == a->btgt) {
4a4d8108 23280+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
f2c43d5f 23281+ au_ftest_ren(a->auren_flags, ISDIR_SRC));
4a4d8108
AM
23282+ if (unlikely(err))
23283+ goto out;
23284+ err = -EINVAL;
23285+ if (unlikely(a->src_h_dentry == a->h_trap))
23286+ goto out;
23287+ }
1facf9fc 23288+
4a4d8108 23289+ err = 0;
5afbbe0d 23290+ if (a->dst_btop != a->btgt)
4a4d8108 23291+ goto out;
1facf9fc 23292+
027c5e7a
AM
23293+ err = -ENOTEMPTY;
23294+ if (unlikely(a->dst_h_dentry == a->h_trap))
23295+ goto out;
23296+
4a4d8108 23297+ err = -EIO;
f2c43d5f 23298+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST);
5527c038
JR
23299+ if (d_really_is_negative(a->dst_dentry)) {
23300+ if (d_is_negative(a->dst_h_dentry))
23301+ err = au_may_add(a->dst_dentry, a->btgt,
23302+ a->dst_h_parent, isdir);
4a4d8108 23303+ } else {
5527c038 23304+ if (unlikely(d_is_negative(a->dst_h_dentry)))
4a4d8108 23305+ goto out;
5527c038
JR
23306+ h_inode = d_inode(a->dst_h_dentry);
23307+ if (h_inode->i_nlink)
23308+ err = au_may_del(a->dst_dentry, a->btgt,
23309+ a->dst_h_parent, isdir);
4a4d8108 23310+ }
1facf9fc 23311+
4f0767ce 23312+out:
4a4d8108
AM
23313+ if (unlikely(err == -ENOENT || err == -EEXIST))
23314+ err = -EIO;
23315+ AuTraceErr(err);
23316+ return err;
23317+}
1facf9fc 23318+
1308ab2a 23319+/* ---------------------------------------------------------------------- */
1facf9fc 23320+
4a4d8108
AM
23321+/*
23322+ * locking order
23323+ * (VFS)
23324+ * - src_dir and dir by lock_rename()
acd2b654 23325+ * - inode if exists
4a4d8108
AM
23326+ * (aufs)
23327+ * - lock all
23328+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
23329+ * + si_read_lock
23330+ * + di_write_lock2_child()
23331+ * + di_write_lock_child()
23332+ * + ii_write_lock_child()
23333+ * + di_write_lock_child2()
23334+ * + ii_write_lock_child2()
23335+ * + src_parent and parent
23336+ * + di_write_lock_parent()
23337+ * + ii_write_lock_parent()
23338+ * + di_write_lock_parent2()
23339+ * + ii_write_lock_parent2()
23340+ * + lower src_dir and dir by vfsub_lock_rename()
23341+ * + verify the every relationships between child and parent. if any
23342+ * of them failed, unlock all and return -EBUSY.
23343+ */
23344+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 23345+{
4a4d8108
AM
23346+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
23347+ a->dst_h_parent, a->dst_hdir);
8b6a4947
AM
23348+ if (au_ftest_ren(a->auren_flags, DIRREN)
23349+ && a->h_root)
23350+ au_hn_inode_unlock(a->h_root);
f2c43d5f 23351+ if (au_ftest_ren(a->auren_flags, MNT_WRITE))
86dc4139 23352+ vfsub_mnt_drop_write(au_br_mnt(a->br));
1308ab2a 23353+}
23354+
4a4d8108 23355+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 23356+{
4a4d8108
AM
23357+ int err;
23358+ unsigned int udba;
1308ab2a 23359+
4a4d8108
AM
23360+ err = 0;
23361+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
23362+ a->src_hdir = au_hi(a->src_dir, a->btgt);
23363+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
23364+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
86dc4139
AM
23365+
23366+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
23367+ if (unlikely(err))
23368+ goto out;
f2c43d5f 23369+ au_fset_ren(a->auren_flags, MNT_WRITE);
8b6a4947
AM
23370+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23371+ struct dentry *root;
23372+ struct inode *dir;
23373+
23374+ /*
23375+ * sbinfo is already locked, so this ii_read_lock is
23376+ * unnecessary. but our debugging feature checks it.
23377+ */
23378+ root = a->src_inode->i_sb->s_root;
23379+ if (root != a->src_parent && root != a->dst_parent) {
23380+ dir = d_inode(root);
23381+ ii_read_lock_parent3(dir);
23382+ a->h_root = au_hi(dir, a->btgt);
23383+ ii_read_unlock(dir);
23384+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3);
23385+ }
23386+ }
4a4d8108
AM
23387+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
23388+ a->dst_h_parent, a->dst_hdir);
23389+ udba = au_opt_udba(a->src_dentry->d_sb);
5527c038
JR
23390+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent)
23391+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent)))
4a4d8108 23392+ err = au_busy_or_stale();
5afbbe0d 23393+ if (!err && au_dbtop(a->src_dentry) == a->btgt)
4a4d8108 23394+ err = au_h_verify(a->src_h_dentry, udba,
5527c038 23395+ d_inode(a->src_h_parent), a->src_h_parent,
4a4d8108 23396+ a->br);
5afbbe0d 23397+ if (!err && au_dbtop(a->dst_dentry) == a->btgt)
4a4d8108 23398+ err = au_h_verify(a->dst_h_dentry, udba,
5527c038 23399+ d_inode(a->dst_h_parent), a->dst_h_parent,
4a4d8108 23400+ a->br);
86dc4139 23401+ if (!err)
4a4d8108 23402+ goto out; /* success */
4a4d8108
AM
23403+
23404+ err = au_busy_or_stale();
4a4d8108 23405+ au_ren_unlock(a);
86dc4139 23406+
4f0767ce 23407+out:
4a4d8108 23408+ return err;
1facf9fc 23409+}
23410+
23411+/* ---------------------------------------------------------------------- */
23412+
4a4d8108 23413+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 23414+{
4a4d8108 23415+ struct inode *dir;
dece6358 23416+
4a4d8108 23417+ dir = a->dst_dir;
be118d29 23418+ inode_inc_iversion(dir);
f2c43d5f 23419+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
4a4d8108
AM
23420+ /* is this updating defined in POSIX? */
23421+ au_cpup_attr_timesizes(a->src_inode);
23422+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 23423+ }
b912730e 23424+ au_dir_ts(dir, a->btgt);
dece6358 23425+
f2c43d5f
AM
23426+ if (a->exchange) {
23427+ dir = a->src_dir;
be118d29 23428+ inode_inc_iversion(dir);
f2c43d5f
AM
23429+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) {
23430+ /* is this updating defined in POSIX? */
23431+ au_cpup_attr_timesizes(a->dst_inode);
23432+ au_cpup_attr_nlink(dir, /*force*/1);
23433+ }
23434+ au_dir_ts(dir, a->btgt);
23435+ }
23436+
23437+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108 23438+ return;
dece6358 23439+
4a4d8108 23440+ dir = a->src_dir;
be118d29 23441+ inode_inc_iversion(dir);
f2c43d5f 23442+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC))
4a4d8108 23443+ au_cpup_attr_nlink(dir, /*force*/1);
b912730e 23444+ au_dir_ts(dir, a->btgt);
1facf9fc 23445+}
23446+
4a4d8108 23447+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 23448+{
5afbbe0d 23449+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
23450+ struct dentry *d, *h_d;
23451+ struct inode *i, *h_i;
23452+ struct super_block *sb;
dece6358 23453+
027c5e7a
AM
23454+ d = a->dst_dentry;
23455+ d_drop(d);
23456+ if (a->h_dst)
23457+ /* already dget-ed by au_ren_or_cpup() */
23458+ au_set_h_dptr(d, a->btgt, a->h_dst);
23459+
23460+ i = a->dst_inode;
23461+ if (i) {
f2c43d5f
AM
23462+ if (!a->exchange) {
23463+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST))
23464+ vfsub_drop_nlink(i);
23465+ else {
23466+ vfsub_dead_dir(i);
23467+ au_cpup_attr_timesizes(i);
23468+ }
23469+ au_update_dbrange(d, /*do_put_zero*/1);
23470+ } else
23471+ au_cpup_attr_nlink(i, /*force*/1);
027c5e7a 23472+ } else {
5afbbe0d
AM
23473+ bbot = a->btgt;
23474+ for (bindex = au_dbtop(d); bindex < bbot; bindex++)
027c5e7a 23475+ au_set_h_dptr(d, bindex, NULL);
5afbbe0d
AM
23476+ bbot = au_dbbot(d);
23477+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++)
027c5e7a
AM
23478+ au_set_h_dptr(d, bindex, NULL);
23479+ au_update_dbrange(d, /*do_put_zero*/0);
23480+ }
23481+
8b6a4947
AM
23482+ if (a->exchange
23483+ || au_ftest_ren(a->auren_flags, DIRREN)) {
23484+ d_drop(a->src_dentry);
23485+ if (au_ftest_ren(a->auren_flags, DIRREN))
23486+ au_set_dbwh(a->src_dentry, -1);
23487+ return;
23488+ }
23489+
4a4d8108 23490+ d = a->src_dentry;
8b6a4947
AM
23491+ au_set_dbwh(d, -1);
23492+ bbot = au_dbbot(d);
23493+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23494+ h_d = au_h_dptr(d, bindex);
23495+ if (h_d)
23496+ au_set_h_dptr(d, bindex, NULL);
23497+ }
23498+ au_set_dbbot(d, a->btgt);
4a4d8108 23499+
8b6a4947
AM
23500+ sb = d->d_sb;
23501+ i = a->src_inode;
23502+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
23503+ return; /* success */
4a4d8108 23504+
8b6a4947
AM
23505+ bbot = au_ibbot(i);
23506+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23507+ h_i = au_h_iptr(i, bindex);
23508+ if (h_i) {
23509+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
23510+ /* ignore this error */
23511+ au_set_h_iptr(i, bindex, NULL, 0);
4a4d8108
AM
23512+ }
23513+ }
8b6a4947 23514+ au_set_ibbot(i, a->btgt);
1308ab2a 23515+}
dece6358 23516+
4a4d8108
AM
23517+/* ---------------------------------------------------------------------- */
23518+
23519+/* mainly for link(2) and rename(2) */
23520+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 23521+{
4a4d8108
AM
23522+ aufs_bindex_t bdiropq, bwh;
23523+ struct dentry *parent;
23524+ struct au_branch *br;
23525+
23526+ parent = dentry->d_parent;
5527c038 23527+ IMustLock(d_inode(parent)); /* dir is locked */
4a4d8108
AM
23528+
23529+ bdiropq = au_dbdiropq(parent);
23530+ bwh = au_dbwh(dentry);
23531+ br = au_sbr(dentry->d_sb, btgt);
23532+ if (au_br_rdonly(br)
23533+ || (0 <= bdiropq && bdiropq < btgt)
23534+ || (0 <= bwh && bwh < btgt))
23535+ btgt = -1;
23536+
23537+ AuDbg("btgt %d\n", btgt);
23538+ return btgt;
1facf9fc 23539+}
23540+
5afbbe0d 23541+/* sets src_btop, dst_btop and btgt */
4a4d8108 23542+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 23543+{
4a4d8108
AM
23544+ int err;
23545+ struct au_wr_dir_args wr_dir_args = {
23546+ /* .force_btgt = -1, */
23547+ .flags = AuWrDir_ADD_ENTRY
23548+ };
dece6358 23549+
5afbbe0d
AM
23550+ a->src_btop = au_dbtop(a->src_dentry);
23551+ a->dst_btop = au_dbtop(a->dst_dentry);
f2c43d5f
AM
23552+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
23553+ || au_ftest_ren(a->auren_flags, ISDIR_DST))
4a4d8108 23554+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
5afbbe0d
AM
23555+ wr_dir_args.force_btgt = a->src_btop;
23556+ if (a->dst_inode && a->dst_btop < a->src_btop)
23557+ wr_dir_args.force_btgt = a->dst_btop;
4a4d8108
AM
23558+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
23559+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
23560+ a->btgt = err;
f2c43d5f
AM
23561+ if (a->exchange)
23562+ au_update_dbtop(a->dst_dentry);
dece6358 23563+
4a4d8108 23564+ return err;
1facf9fc 23565+}
23566+
4a4d8108 23567+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 23568+{
4a4d8108
AM
23569+ a->h_path.dentry = a->src_h_parent;
23570+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
f2c43d5f 23571+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) {
4a4d8108
AM
23572+ a->h_path.dentry = a->dst_h_parent;
23573+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
23574+ }
1facf9fc 23575+
f2c43d5f
AM
23576+ au_fclr_ren(a->auren_flags, DT_DSTDIR);
23577+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC)
23578+ && !a->exchange)
4a4d8108 23579+ return;
dece6358 23580+
4a4d8108
AM
23581+ a->h_path.dentry = a->src_h_dentry;
23582+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
5527c038 23583+ if (d_is_positive(a->dst_h_dentry)) {
f2c43d5f 23584+ au_fset_ren(a->auren_flags, DT_DSTDIR);
4a4d8108
AM
23585+ a->h_path.dentry = a->dst_h_dentry;
23586+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
23587+ }
1308ab2a 23588+}
dece6358 23589+
4a4d8108 23590+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 23591+{
4a4d8108 23592+ struct dentry *h_d;
febd17d6 23593+ struct inode *h_inode;
4a4d8108
AM
23594+
23595+ au_dtime_revert(a->src_dt + AuPARENT);
f2c43d5f 23596+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23597+ au_dtime_revert(a->dst_dt + AuPARENT);
23598+
f2c43d5f 23599+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) {
4a4d8108 23600+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23601+ h_inode = d_inode(h_d);
23602+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23603+ au_dtime_revert(a->src_dt + AuCHILD);
febd17d6 23604+ inode_unlock(h_inode);
4a4d8108 23605+
f2c43d5f 23606+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) {
4a4d8108 23607+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23608+ h_inode = d_inode(h_d);
23609+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23610+ au_dtime_revert(a->dst_dt + AuCHILD);
febd17d6 23611+ inode_unlock(h_inode);
1facf9fc 23612+ }
23613+ }
23614+}
23615+
4a4d8108
AM
23616+/* ---------------------------------------------------------------------- */
23617+
23618+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
f2c43d5f
AM
23619+ struct inode *_dst_dir, struct dentry *_dst_dentry,
23620+ unsigned int _flags)
1facf9fc 23621+{
f2c43d5f 23622+ int err, lock_flags;
8b6a4947 23623+ void *rev;
4a4d8108
AM
23624+ /* reduce stack space */
23625+ struct au_ren_args *a;
f2c43d5f 23626+ struct au_pin pin;
4a4d8108 23627+
f2c43d5f 23628+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags);
4a4d8108
AM
23629+ IMustLock(_src_dir);
23630+ IMustLock(_dst_dir);
23631+
f2c43d5f
AM
23632+ err = -EINVAL;
23633+ if (unlikely(_flags & RENAME_WHITEOUT))
23634+ goto out;
23635+
4a4d8108
AM
23636+ err = -ENOMEM;
23637+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
23638+ a = kzalloc(sizeof(*a), GFP_NOFS);
23639+ if (unlikely(!a))
23640+ goto out;
23641+
f2c43d5f 23642+ a->flags = _flags;
acd2b654
AM
23643+ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8)
23644+ && RENAME_EXCHANGE > U8_MAX);
f2c43d5f 23645+ a->exchange = _flags & RENAME_EXCHANGE;
4a4d8108
AM
23646+ a->src_dir = _src_dir;
23647+ a->src_dentry = _src_dentry;
5527c038
JR
23648+ a->src_inode = NULL;
23649+ if (d_really_is_positive(a->src_dentry))
23650+ a->src_inode = d_inode(a->src_dentry);
4a4d8108
AM
23651+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
23652+ a->dst_dir = _dst_dir;
23653+ a->dst_dentry = _dst_dentry;
5527c038
JR
23654+ a->dst_inode = NULL;
23655+ if (d_really_is_positive(a->dst_dentry))
23656+ a->dst_inode = d_inode(a->dst_dentry);
4a4d8108
AM
23657+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
23658+ if (a->dst_inode) {
f2c43d5f
AM
23659+ /*
23660+ * if EXCHANGE && src is non-dir && dst is dir,
23661+ * dst is not locked.
23662+ */
23663+ /* IMustLock(a->dst_inode); */
4a4d8108 23664+ au_igrab(a->dst_inode);
1facf9fc 23665+ }
1facf9fc 23666+
4a4d8108 23667+ err = -ENOTDIR;
f2c43d5f 23668+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
2000de60 23669+ if (d_is_dir(a->src_dentry)) {
f2c43d5f
AM
23670+ au_fset_ren(a->auren_flags, ISDIR_SRC);
23671+ if (unlikely(!a->exchange
23672+ && d_really_is_positive(a->dst_dentry)
2000de60 23673+ && !d_is_dir(a->dst_dentry)))
4a4d8108 23674+ goto out_free;
f2c43d5f
AM
23675+ lock_flags |= AuLock_DIRS;
23676+ }
23677+ if (a->dst_inode && d_is_dir(a->dst_dentry)) {
23678+ au_fset_ren(a->auren_flags, ISDIR_DST);
23679+ if (unlikely(!a->exchange
23680+ && d_really_is_positive(a->src_dentry)
23681+ && !d_is_dir(a->src_dentry)))
23682+ goto out_free;
23683+ lock_flags |= AuLock_DIRS;
b95c5147 23684+ }
8b6a4947
AM
23685+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
23686+ lock_flags);
e49829fe
JR
23687+ if (unlikely(err))
23688+ goto out_free;
1facf9fc 23689+
027c5e7a
AM
23690+ err = au_d_hashed_positive(a->src_dentry);
23691+ if (unlikely(err))
23692+ goto out_unlock;
23693+ err = -ENOENT;
23694+ if (a->dst_inode) {
23695+ /*
f2c43d5f 23696+ * If it is a dir, VFS unhash it before this
027c5e7a
AM
23697+ * function. It means we cannot rely upon d_unhashed().
23698+ */
23699+ if (unlikely(!a->dst_inode->i_nlink))
23700+ goto out_unlock;
f2c43d5f 23701+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) {
027c5e7a 23702+ err = au_d_hashed_positive(a->dst_dentry);
f2c43d5f 23703+ if (unlikely(err && !a->exchange))
027c5e7a
AM
23704+ goto out_unlock;
23705+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
23706+ goto out_unlock;
23707+ } else if (unlikely(d_unhashed(a->dst_dentry)))
23708+ goto out_unlock;
23709+
7eafdf33
AM
23710+ /*
23711+ * is it possible?
79b8bda9 23712+ * yes, it happened (in linux-3.3-rcN) but I don't know why.
7eafdf33
AM
23713+ * there may exist a problem somewhere else.
23714+ */
23715+ err = -EINVAL;
5527c038 23716+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry)))
7eafdf33
AM
23717+ goto out_unlock;
23718+
f2c43d5f 23719+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */
4a4d8108 23720+ di_write_lock_parent(a->dst_parent);
1facf9fc 23721+
4a4d8108
AM
23722+ /* which branch we process */
23723+ err = au_ren_wbr(a);
23724+ if (unlikely(err < 0))
027c5e7a 23725+ goto out_parent;
4a4d8108 23726+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
86dc4139 23727+ a->h_path.mnt = au_br_mnt(a->br);
1facf9fc 23728+
4a4d8108
AM
23729+ /* are they available to be renamed */
23730+ err = au_ren_may_dir(a);
23731+ if (unlikely(err))
23732+ goto out_children;
1facf9fc 23733+
4a4d8108 23734+ /* prepare the writable parent dir on the same branch */
5afbbe0d 23735+ if (a->dst_btop == a->btgt) {
f2c43d5f 23736+ au_fset_ren(a->auren_flags, WHDST);
4a4d8108
AM
23737+ } else {
23738+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
23739+ if (unlikely(err))
23740+ goto out_children;
23741+ }
1facf9fc 23742+
f2c43d5f
AM
23743+ err = 0;
23744+ if (!a->exchange) {
23745+ if (a->src_dir != a->dst_dir) {
23746+ /*
23747+ * this temporary unlock is safe,
23748+ * because both dir->i_mutex are locked.
23749+ */
23750+ di_write_unlock(a->dst_parent);
23751+ di_write_lock_parent(a->src_parent);
23752+ err = au_wr_dir_need_wh(a->src_dentry,
23753+ au_ftest_ren(a->auren_flags,
23754+ ISDIR_SRC),
23755+ &a->btgt);
23756+ di_write_unlock(a->src_parent);
23757+ di_write_lock2_parent(a->src_parent, a->dst_parent,
23758+ /*isdir*/1);
23759+ au_fclr_ren(a->auren_flags, ISSAMEDIR);
23760+ } else
23761+ err = au_wr_dir_need_wh(a->src_dentry,
23762+ au_ftest_ren(a->auren_flags,
23763+ ISDIR_SRC),
23764+ &a->btgt);
23765+ }
4a4d8108
AM
23766+ if (unlikely(err < 0))
23767+ goto out_children;
23768+ if (err)
f2c43d5f 23769+ au_fset_ren(a->auren_flags, WHSRC);
1facf9fc 23770+
86dc4139 23771+ /* cpup src */
5afbbe0d 23772+ if (a->src_btop != a->btgt) {
86dc4139
AM
23773+ err = au_pin(&pin, a->src_dentry, a->btgt,
23774+ au_opt_udba(a->src_dentry->d_sb),
23775+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 23776+ if (!err) {
c2b27bf2
AM
23777+ struct au_cp_generic cpg = {
23778+ .dentry = a->src_dentry,
23779+ .bdst = a->btgt,
5afbbe0d 23780+ .bsrc = a->src_btop,
c2b27bf2
AM
23781+ .len = -1,
23782+ .pin = &pin,
23783+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23784+ };
5afbbe0d 23785+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop);
c2b27bf2 23786+ err = au_sio_cpup_simple(&cpg);
367653fa 23787+ au_unpin(&pin);
86dc4139 23788+ }
86dc4139
AM
23789+ if (unlikely(err))
23790+ goto out_children;
5afbbe0d 23791+ a->src_btop = a->btgt;
86dc4139 23792+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt);
f2c43d5f
AM
23793+ if (!a->exchange)
23794+ au_fset_ren(a->auren_flags, WHSRC);
23795+ }
23796+
23797+ /* cpup dst */
23798+ if (a->exchange && a->dst_inode
23799+ && a->dst_btop != a->btgt) {
23800+ err = au_pin(&pin, a->dst_dentry, a->btgt,
23801+ au_opt_udba(a->dst_dentry->d_sb),
23802+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
23803+ if (!err) {
23804+ struct au_cp_generic cpg = {
23805+ .dentry = a->dst_dentry,
23806+ .bdst = a->btgt,
23807+ .bsrc = a->dst_btop,
23808+ .len = -1,
23809+ .pin = &pin,
23810+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23811+ };
23812+ err = au_sio_cpup_simple(&cpg);
23813+ au_unpin(&pin);
23814+ }
23815+ if (unlikely(err))
23816+ goto out_children;
23817+ a->dst_btop = a->btgt;
23818+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt);
86dc4139
AM
23819+ }
23820+
4a4d8108
AM
23821+ /* lock them all */
23822+ err = au_ren_lock(a);
23823+ if (unlikely(err))
86dc4139 23824+ /* leave the copied-up one */
4a4d8108 23825+ goto out_children;
1facf9fc 23826+
f2c43d5f
AM
23827+ if (!a->exchange) {
23828+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
23829+ err = au_may_ren(a);
23830+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
23831+ err = -ENAMETOOLONG;
23832+ if (unlikely(err))
23833+ goto out_hdir;
23834+ }
1facf9fc 23835+
4a4d8108
AM
23836+ /* store timestamps to be revertible */
23837+ au_ren_dt(a);
1facf9fc 23838+
8b6a4947
AM
23839+ /* store dirren info */
23840+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23841+ err = au_dr_rename(a->src_dentry, a->btgt,
23842+ &a->dst_dentry->d_name, &rev);
23843+ AuTraceErr(err);
23844+ if (unlikely(err))
23845+ goto out_dt;
23846+ }
23847+
4a4d8108
AM
23848+ /* here we go */
23849+ err = do_rename(a);
23850+ if (unlikely(err))
8b6a4947
AM
23851+ goto out_dirren;
23852+
23853+ if (au_ftest_ren(a->auren_flags, DIRREN))
23854+ au_dr_rename_fin(a->src_dentry, a->btgt, rev);
4a4d8108
AM
23855+
23856+ /* update dir attributes */
23857+ au_ren_refresh_dir(a);
23858+
23859+ /* dput/iput all lower dentries */
23860+ au_ren_refresh(a);
23861+
23862+ goto out_hdir; /* success */
23863+
8b6a4947
AM
23864+out_dirren:
23865+ if (au_ftest_ren(a->auren_flags, DIRREN))
23866+ au_dr_rename_rev(a->src_dentry, a->btgt, rev);
4f0767ce 23867+out_dt:
4a4d8108 23868+ au_ren_rev_dt(err, a);
4f0767ce 23869+out_hdir:
4a4d8108 23870+ au_ren_unlock(a);
4f0767ce 23871+out_children:
4a4d8108 23872+ au_nhash_wh_free(&a->whlist);
5afbbe0d
AM
23873+ if (err && a->dst_inode && a->dst_btop != a->btgt) {
23874+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt);
027c5e7a 23875+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
5afbbe0d 23876+ au_set_dbtop(a->dst_dentry, a->dst_btop);
4a4d8108 23877+ }
027c5e7a 23878+out_parent:
f2c43d5f 23879+ if (!err) {
8b6a4947
AM
23880+ if (d_unhashed(a->src_dentry))
23881+ au_fset_ren(a->auren_flags, DROPPED_SRC);
23882+ if (d_unhashed(a->dst_dentry))
23883+ au_fset_ren(a->auren_flags, DROPPED_DST);
f2c43d5f
AM
23884+ if (!a->exchange)
23885+ d_move(a->src_dentry, a->dst_dentry);
8b6a4947 23886+ else {
f2c43d5f 23887+ d_exchange(a->src_dentry, a->dst_dentry);
8b6a4947
AM
23888+ if (au_ftest_ren(a->auren_flags, DROPPED_DST))
23889+ d_drop(a->dst_dentry);
23890+ }
23891+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC))
23892+ d_drop(a->src_dentry);
f2c43d5f 23893+ } else {
5afbbe0d 23894+ au_update_dbtop(a->dst_dentry);
027c5e7a
AM
23895+ if (!a->dst_inode)
23896+ d_drop(a->dst_dentry);
23897+ }
f2c43d5f 23898+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23899+ di_write_unlock(a->dst_parent);
23900+ else
23901+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 23902+out_unlock:
4a4d8108 23903+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 23904+out_free:
4a4d8108
AM
23905+ iput(a->dst_inode);
23906+ if (a->thargs)
23907+ au_whtmp_rmdir_free(a->thargs);
9f237c51 23908+ au_kfree_rcu(a);
4f0767ce 23909+out:
4a4d8108
AM
23910+ AuTraceErr(err);
23911+ return err;
1308ab2a 23912+}
7f207e10 23913diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
eca34b5c
AM
23914--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
23915+++ linux/fs/aufs/Kconfig 2019-07-11 15:42:14.458904362 +0200
2121bcd9
AM
23916@@ -0,0 +1,199 @@
23917+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
23918+config AUFS_FS
23919+ tristate "Aufs (Advanced multi layered unification filesystem) support"
4a4d8108
AM
23920+ help
23921+ Aufs is a stackable unification filesystem such as Unionfs,
23922+ which unifies several directories and provides a merged single
23923+ directory.
23924+ In the early days, aufs was entirely re-designed and
23925+ re-implemented Unionfs Version 1.x series. Introducing many
23926+ original ideas, approaches and improvements, it becomes totally
23927+ different from Unionfs while keeping the basic features.
1facf9fc 23928+
4a4d8108
AM
23929+if AUFS_FS
23930+choice
23931+ prompt "Maximum number of branches"
23932+ default AUFS_BRANCH_MAX_127
23933+ help
23934+ Specifies the maximum number of branches (or member directories)
23935+ in a single aufs. The larger value consumes more system
23936+ resources and has a minor impact to performance.
23937+config AUFS_BRANCH_MAX_127
23938+ bool "127"
23939+ help
23940+ Specifies the maximum number of branches (or member directories)
23941+ in a single aufs. The larger value consumes more system
23942+ resources and has a minor impact to performance.
23943+config AUFS_BRANCH_MAX_511
23944+ bool "511"
23945+ help
23946+ Specifies the maximum number of branches (or member directories)
23947+ in a single aufs. The larger value consumes more system
23948+ resources and has a minor impact to performance.
23949+config AUFS_BRANCH_MAX_1023
23950+ bool "1023"
23951+ help
23952+ Specifies the maximum number of branches (or member directories)
23953+ in a single aufs. The larger value consumes more system
23954+ resources and has a minor impact to performance.
23955+config AUFS_BRANCH_MAX_32767
23956+ bool "32767"
23957+ help
23958+ Specifies the maximum number of branches (or member directories)
23959+ in a single aufs. The larger value consumes more system
23960+ resources and has a minor impact to performance.
23961+endchoice
1facf9fc 23962+
e49829fe
JR
23963+config AUFS_SBILIST
23964+ bool
23965+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
23966+ default y
23967+ help
23968+ Automatic configuration for internal use.
23969+ When aufs supports Magic SysRq or /proc, enabled automatically.
23970+
4a4d8108
AM
23971+config AUFS_HNOTIFY
23972+ bool "Detect direct branch access (bypassing aufs)"
23973+ help
23974+ If you want to modify files on branches directly, eg. bypassing aufs,
23975+ and want aufs to detect the changes of them fully, then enable this
23976+ option and use 'udba=notify' mount option.
7f207e10 23977+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
23978+ It will have a negative impact to the performance.
23979+ See detail in aufs.5.
dece6358 23980+
4a4d8108
AM
23981+choice
23982+ prompt "method" if AUFS_HNOTIFY
23983+ default AUFS_HFSNOTIFY
23984+config AUFS_HFSNOTIFY
23985+ bool "fsnotify"
23986+ select FSNOTIFY
4a4d8108 23987+endchoice
1facf9fc 23988+
4a4d8108
AM
23989+config AUFS_EXPORT
23990+ bool "NFS-exportable aufs"
2cbb1c4b 23991+ depends on EXPORTFS
4a4d8108
AM
23992+ help
23993+ If you want to export your mounted aufs via NFS, then enable this
23994+ option. There are several requirements for this configuration.
23995+ See detail in aufs.5.
1facf9fc 23996+
4a4d8108
AM
23997+config AUFS_INO_T_64
23998+ bool
23999+ depends on AUFS_EXPORT
24000+ depends on 64BIT && !(ALPHA || S390)
24001+ default y
24002+ help
24003+ Automatic configuration for internal use.
24004+ /* typedef unsigned long/int __kernel_ino_t */
24005+ /* alpha and s390x are int */
1facf9fc 24006+
c1595e42
JR
24007+config AUFS_XATTR
24008+ bool "support for XATTR/EA (including Security Labels)"
24009+ help
24010+ If your branch fs supports XATTR/EA and you want to make them
24011+ available in aufs too, then enable this opsion and specify the
24012+ branch attributes for EA.
24013+ See detail in aufs.5.
24014+
076b876e
AM
24015+config AUFS_FHSM
24016+ bool "File-based Hierarchical Storage Management"
24017+ help
24018+ Hierarchical Storage Management (or HSM) is a well-known feature
24019+ in the storage world. Aufs provides this feature as file-based.
24020+ with multiple branches.
24021+ These multiple branches are prioritized, ie. the topmost one
24022+ should be the fastest drive and be used heavily.
24023+
4a4d8108
AM
24024+config AUFS_RDU
24025+ bool "Readdir in userspace"
24026+ help
24027+ Aufs has two methods to provide a merged view for a directory,
24028+ by a user-space library and by kernel-space natively. The latter
24029+ is always enabled but sometimes large and slow.
24030+ If you enable this option, install the library in aufs2-util
24031+ package, and set some environment variables for your readdir(3),
24032+ then the work will be handled in user-space which generally
24033+ shows better performance in most cases.
24034+ See detail in aufs.5.
1facf9fc 24035+
8b6a4947
AM
24036+config AUFS_DIRREN
24037+ bool "Workaround for rename(2)-ing a directory"
24038+ help
24039+ By default, aufs returns EXDEV error in renameing a dir who has
24040+ his child on the lower branch, since it is a bad idea to issue
24041+ rename(2) internally for every lower branch. But user may not
24042+ accept this behaviour. So here is a workaround to allow such
24043+ rename(2) and store some extra infromation on the writable
24044+ branch. Obviously this costs high (and I don't like it).
24045+ To use this feature, you need to enable this configuration AND
24046+ to specify the mount option `dirren.'
24047+ See details in aufs.5 and the design documents.
24048+
4a4d8108
AM
24049+config AUFS_SHWH
24050+ bool "Show whiteouts"
24051+ help
24052+ If you want to make the whiteouts in aufs visible, then enable
24053+ this option and specify 'shwh' mount option. Although it may
24054+ sounds like philosophy or something, but in technically it
24055+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 24056+
4a4d8108
AM
24057+config AUFS_BR_RAMFS
24058+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
24059+ help
24060+ If you want to use ramfs as an aufs branch fs, then enable this
24061+ option. Generally tmpfs is recommended.
24062+ Aufs prohibited them to be a branch fs by default, because
24063+ initramfs becomes unusable after switch_root or something
24064+ generally. If you sets initramfs as an aufs branch and boot your
24065+ system by switch_root, you will meet a problem easily since the
24066+ files in initramfs may be inaccessible.
24067+ Unless you are going to use ramfs as an aufs branch fs without
24068+ switch_root or something, leave it N.
1facf9fc 24069+
4a4d8108
AM
24070+config AUFS_BR_FUSE
24071+ bool "Fuse fs as an aufs branch"
24072+ depends on FUSE_FS
24073+ select AUFS_POLL
24074+ help
24075+ If you want to use fuse-based userspace filesystem as an aufs
24076+ branch fs, then enable this option.
24077+ It implements the internal poll(2) operation which is
24078+ implemented by fuse only (curretnly).
1facf9fc 24079+
4a4d8108
AM
24080+config AUFS_POLL
24081+ bool
24082+ help
24083+ Automatic configuration for internal use.
1facf9fc 24084+
4a4d8108
AM
24085+config AUFS_BR_HFSPLUS
24086+ bool "Hfsplus as an aufs branch"
24087+ depends on HFSPLUS_FS
24088+ default y
24089+ help
24090+ If you want to use hfsplus fs as an aufs branch fs, then enable
24091+ this option. This option introduces a small overhead at
24092+ copying-up a file on hfsplus.
1facf9fc 24093+
4a4d8108
AM
24094+config AUFS_BDEV_LOOP
24095+ bool
24096+ depends on BLK_DEV_LOOP
24097+ default y
24098+ help
24099+ Automatic configuration for internal use.
24100+ Convert =[ym] into =y.
1308ab2a 24101+
4a4d8108
AM
24102+config AUFS_DEBUG
24103+ bool "Debug aufs"
24104+ help
24105+ Enable this to compile aufs internal debug code.
24106+ It will have a negative impact to the performance.
24107+
24108+config AUFS_MAGIC_SYSRQ
24109+ bool
24110+ depends on AUFS_DEBUG && MAGIC_SYSRQ
24111+ default y
24112+ help
24113+ Automatic configuration for internal use.
24114+ When aufs supports Magic SysRq, enabled automatically.
24115+endif
acd2b654 24116diff -urN /usr/share/empty/fs/aufs/lcnt.h linux/fs/aufs/lcnt.h
eca34b5c
AM
24117--- /usr/share/empty/fs/aufs/lcnt.h 1970-01-01 01:00:00.000000000 +0100
24118+++ linux/fs/aufs/lcnt.h 2019-07-11 15:42:14.468904634 +0200
acd2b654
AM
24119@@ -0,0 +1,186 @@
24120+/* SPDX-License-Identifier: GPL-2.0 */
24121+/*
ba1aed25 24122+ * Copyright (C) 2018-2019 Junjiro R. Okajima
acd2b654
AM
24123+ *
24124+ * This program, aufs is free software; you can redistribute it and/or modify
24125+ * it under the terms of the GNU General Public License as published by
24126+ * the Free Software Foundation; either version 2 of the License, or
24127+ * (at your option) any later version.
24128+ *
24129+ * This program is distributed in the hope that it will be useful,
24130+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24131+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24132+ * GNU General Public License for more details.
24133+ *
24134+ * You should have received a copy of the GNU General Public License
24135+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24136+ */
24137+
24138+/*
24139+ * simple long counter wrapper
24140+ */
24141+
24142+#ifndef __AUFS_LCNT_H__
24143+#define __AUFS_LCNT_H__
24144+
24145+#ifdef __KERNEL__
24146+
24147+#include "debug.h"
24148+
24149+#define AuLCntATOMIC 1
24150+#define AuLCntPCPUCNT 2
24151+/*
24152+ * why does percpu_refcount require extra synchronize_rcu()s in
24153+ * au_br_do_free()
24154+ */
24155+#define AuLCntPCPUREF 3
24156+
24157+/* #define AuLCntChosen AuLCntATOMIC */
24158+#define AuLCntChosen AuLCntPCPUCNT
24159+/* #define AuLCntChosen AuLCntPCPUREF */
24160+
24161+#if AuLCntChosen == AuLCntATOMIC
24162+#include <linux/atomic.h>
24163+
24164+typedef atomic_long_t au_lcnt_t;
24165+
24166+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24167+{
24168+ atomic_long_set(cnt, 0);
24169+ return 0;
24170+}
24171+
24172+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24173+{
24174+ /* empty */
24175+}
24176+
24177+static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused,
24178+ int do_sync __maybe_unused)
24179+{
24180+ /* empty */
24181+}
24182+
24183+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24184+{
24185+ atomic_long_inc(cnt);
24186+}
24187+
24188+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24189+{
24190+ atomic_long_dec(cnt);
24191+}
24192+
24193+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24194+{
24195+ return atomic_long_read(cnt);
24196+}
24197+#endif
24198+
24199+#if AuLCntChosen == AuLCntPCPUCNT
24200+#include <linux/percpu_counter.h>
24201+
24202+typedef struct percpu_counter au_lcnt_t;
24203+
24204+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24205+{
24206+ return percpu_counter_init(cnt, 0, GFP_NOFS);
24207+}
24208+
24209+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24210+{
24211+ /* empty */
24212+}
24213+
24214+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused)
24215+{
24216+ percpu_counter_destroy(cnt);
24217+}
24218+
24219+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24220+{
24221+ percpu_counter_inc(cnt);
24222+}
24223+
24224+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24225+{
24226+ percpu_counter_dec(cnt);
24227+}
24228+
24229+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24230+{
24231+ s64 n;
24232+
24233+ n = percpu_counter_sum(cnt);
24234+ BUG_ON(n < 0);
24235+ if (LONG_MAX != LLONG_MAX
24236+ && n > LONG_MAX)
24237+ AuWarn1("%s\n", "wrap-around");
24238+
24239+ return n;
24240+}
24241+#endif
24242+
24243+#if AuLCntChosen == AuLCntPCPUREF
24244+#include <linux/percpu-refcount.h>
24245+
24246+typedef struct percpu_ref au_lcnt_t;
24247+
24248+static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release)
24249+{
24250+ if (!release)
24251+ release = percpu_ref_exit;
24252+ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS);
24253+}
24254+
24255+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24256+{
24257+ synchronize_rcu();
24258+}
24259+
24260+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync)
24261+{
24262+ percpu_ref_kill(cnt);
24263+ if (do_sync)
24264+ au_lcnt_wait_for_fin(cnt);
24265+}
24266+
24267+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24268+{
24269+ percpu_ref_get(cnt);
24270+}
24271+
24272+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24273+{
24274+ percpu_ref_put(cnt);
24275+}
24276+
24277+/*
24278+ * avoid calling this func as possible.
24279+ */
24280+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev)
24281+{
24282+ long l;
24283+
24284+ percpu_ref_switch_to_atomic_sync(cnt);
24285+ l = atomic_long_read(&cnt->count);
24286+ if (do_rev)
24287+ percpu_ref_switch_to_percpu(cnt);
24288+
24289+ /* percpu_ref is initialized by 1 instead of 0 */
24290+ return l - 1;
24291+}
24292+#endif
24293+
24294+#ifdef CONFIG_AUFS_DEBUG
24295+#define AuLCntZero(val) do { \
24296+ long l = val; \
24297+ if (l) \
24298+ AuDbg("%s = %ld\n", #val, l); \
24299+} while (0)
24300+#else
24301+#define AuLCntZero(val) do {} while (0)
24302+#endif
24303+
24304+#endif /* __KERNEL__ */
24305+#endif /* __AUFS_LCNT_H__ */
7f207e10 24306diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
eca34b5c
AM
24307--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
24308+++ linux/fs/aufs/loop.c 2019-07-11 15:42:14.468904634 +0200
062440b3 24309@@ -0,0 +1,148 @@
cd7a4cd9 24310+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24311+/*
ba1aed25 24312+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 24313+ *
24314+ * This program, aufs is free software; you can redistribute it and/or modify
24315+ * it under the terms of the GNU General Public License as published by
24316+ * the Free Software Foundation; either version 2 of the License, or
24317+ * (at your option) any later version.
dece6358
AM
24318+ *
24319+ * This program is distributed in the hope that it will be useful,
24320+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24321+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24322+ * GNU General Public License for more details.
24323+ *
24324+ * You should have received a copy of the GNU General Public License
523b37e3 24325+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24326+ */
24327+
24328+/*
24329+ * support for loopback block device as a branch
24330+ */
24331+
1facf9fc 24332+#include "aufs.h"
24333+
392086de
AM
24334+/* added into drivers/block/loop.c */
24335+static struct file *(*backing_file_func)(struct super_block *sb);
24336+
1facf9fc 24337+/*
24338+ * test if two lower dentries have overlapping branches.
24339+ */
b752ccd1 24340+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 24341+{
b752ccd1 24342+ struct super_block *h_sb;
392086de
AM
24343+ struct file *backing_file;
24344+
24345+ if (unlikely(!backing_file_func)) {
24346+ /* don't load "loop" module here */
24347+ backing_file_func = symbol_get(loop_backing_file);
24348+ if (unlikely(!backing_file_func))
24349+ /* "loop" module is not loaded */
24350+ return 0;
24351+ }
1facf9fc 24352+
b752ccd1 24353+ h_sb = h_adding->d_sb;
392086de
AM
24354+ backing_file = backing_file_func(h_sb);
24355+ if (!backing_file)
1facf9fc 24356+ return 0;
24357+
2000de60 24358+ h_adding = backing_file->f_path.dentry;
b752ccd1
AM
24359+ /*
24360+ * h_adding can be local NFS.
24361+ * in this case aufs cannot detect the loop.
24362+ */
24363+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 24364+ return 1;
b752ccd1 24365+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 24366+}
24367+
24368+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
24369+int au_test_loopback_kthread(void)
24370+{
b752ccd1
AM
24371+ int ret;
24372+ struct task_struct *tsk = current;
a2a7ad62 24373+ char c, comm[sizeof(tsk->comm)];
b752ccd1
AM
24374+
24375+ ret = 0;
24376+ if (tsk->flags & PF_KTHREAD) {
a2a7ad62
AM
24377+ get_task_comm(comm, tsk);
24378+ c = comm[4];
b752ccd1 24379+ ret = ('0' <= c && c <= '9'
a2a7ad62 24380+ && !strncmp(comm, "loop", 4));
b752ccd1 24381+ }
1facf9fc 24382+
b752ccd1 24383+ return ret;
1facf9fc 24384+}
87a755f4
AM
24385+
24386+/* ---------------------------------------------------------------------- */
24387+
24388+#define au_warn_loopback_step 16
24389+static int au_warn_loopback_nelem = au_warn_loopback_step;
24390+static unsigned long *au_warn_loopback_array;
24391+
24392+void au_warn_loopback(struct super_block *h_sb)
24393+{
24394+ int i, new_nelem;
24395+ unsigned long *a, magic;
24396+ static DEFINE_SPINLOCK(spin);
24397+
24398+ magic = h_sb->s_magic;
24399+ spin_lock(&spin);
24400+ a = au_warn_loopback_array;
24401+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
24402+ if (a[i] == magic) {
24403+ spin_unlock(&spin);
24404+ return;
24405+ }
24406+
24407+ /* h_sb is new to us, print it */
24408+ if (i < au_warn_loopback_nelem) {
24409+ a[i] = magic;
24410+ goto pr;
24411+ }
24412+
24413+ /* expand the array */
24414+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
24415+ a = au_kzrealloc(au_warn_loopback_array,
24416+ au_warn_loopback_nelem * sizeof(unsigned long),
e2f27e51
AM
24417+ new_nelem * sizeof(unsigned long), GFP_ATOMIC,
24418+ /*may_shrink*/0);
87a755f4
AM
24419+ if (a) {
24420+ au_warn_loopback_nelem = new_nelem;
24421+ au_warn_loopback_array = a;
24422+ a[i] = magic;
24423+ goto pr;
24424+ }
24425+
24426+ spin_unlock(&spin);
24427+ AuWarn1("realloc failed, ignored\n");
24428+ return;
24429+
24430+pr:
24431+ spin_unlock(&spin);
0c3ec466
AM
24432+ pr_warn("you may want to try another patch for loopback file "
24433+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
24434+}
24435+
24436+int au_loopback_init(void)
24437+{
24438+ int err;
24439+ struct super_block *sb __maybe_unused;
24440+
fbc438ed 24441+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array));
87a755f4
AM
24442+
24443+ err = 0;
24444+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
24445+ sizeof(unsigned long), GFP_NOFS);
24446+ if (unlikely(!au_warn_loopback_array))
24447+ err = -ENOMEM;
24448+
24449+ return err;
24450+}
24451+
24452+void au_loopback_fin(void)
24453+{
79b8bda9
AM
24454+ if (backing_file_func)
24455+ symbol_put(loop_backing_file);
9f237c51 24456+ au_kfree_try_rcu(au_warn_loopback_array);
87a755f4 24457+}
7f207e10 24458diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
eca34b5c
AM
24459--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
24460+++ linux/fs/aufs/loop.h 2019-07-11 15:42:14.468904634 +0200
eca801bf 24461@@ -0,0 +1,55 @@
062440b3 24462+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24463+/*
ba1aed25 24464+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 24465+ *
24466+ * This program, aufs is free software; you can redistribute it and/or modify
24467+ * it under the terms of the GNU General Public License as published by
24468+ * the Free Software Foundation; either version 2 of the License, or
24469+ * (at your option) any later version.
dece6358
AM
24470+ *
24471+ * This program is distributed in the hope that it will be useful,
24472+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24473+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24474+ * GNU General Public License for more details.
24475+ *
24476+ * You should have received a copy of the GNU General Public License
523b37e3 24477+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24478+ */
24479+
24480+/*
24481+ * support for loopback mount as a branch
24482+ */
24483+
24484+#ifndef __AUFS_LOOP_H__
24485+#define __AUFS_LOOP_H__
24486+
24487+#ifdef __KERNEL__
24488+
dece6358
AM
24489+struct dentry;
24490+struct super_block;
1facf9fc 24491+
24492+#ifdef CONFIG_AUFS_BDEV_LOOP
392086de
AM
24493+/* drivers/block/loop.c */
24494+struct file *loop_backing_file(struct super_block *sb);
24495+
1facf9fc 24496+/* loop.c */
b752ccd1 24497+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 24498+int au_test_loopback_kthread(void);
87a755f4
AM
24499+void au_warn_loopback(struct super_block *h_sb);
24500+
24501+int au_loopback_init(void);
24502+void au_loopback_fin(void);
1facf9fc 24503+#else
83b672a5 24504+AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf 24505+
4a4d8108 24506+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 24507+ struct dentry *h_adding)
4a4d8108 24508+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
24509+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
24510+
24511+AuStubInt0(au_loopback_init, void)
24512+AuStubVoid(au_loopback_fin, void)
1facf9fc 24513+#endif /* BLK_DEV_LOOP */
24514+
24515+#endif /* __KERNEL__ */
24516+#endif /* __AUFS_LOOP_H__ */
7f207e10 24517diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
eca34b5c
AM
24518--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
24519+++ linux/fs/aufs/magic.mk 2019-07-11 15:42:14.468904634 +0200
2121bcd9
AM
24520@@ -0,0 +1,31 @@
24521+# SPDX-License-Identifier: GPL-2.0
1facf9fc 24522+
24523+# defined in ${srctree}/fs/fuse/inode.c
24524+# tristate
24525+ifdef CONFIG_FUSE_FS
24526+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
24527+endif
24528+
1facf9fc 24529+# defined in ${srctree}/fs/xfs/xfs_sb.h
24530+# tristate
24531+ifdef CONFIG_XFS_FS
24532+ccflags-y += -DXFS_SB_MAGIC=0x58465342
24533+endif
24534+
24535+# defined in ${srctree}/fs/configfs/mount.c
24536+# tristate
24537+ifdef CONFIG_CONFIGFS_FS
24538+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
24539+endif
24540+
1facf9fc 24541+# defined in ${srctree}/fs/ubifs/ubifs.h
24542+# tristate
24543+ifdef CONFIG_UBIFS_FS
24544+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
24545+endif
4a4d8108
AM
24546+
24547+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
24548+# tristate
24549+ifdef CONFIG_HFSPLUS_FS
24550+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
24551+endif
7f207e10 24552diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
eca34b5c
AM
24553--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
24554+++ linux/fs/aufs/Makefile 2019-07-11 15:42:14.462237786 +0200
2121bcd9
AM
24555@@ -0,0 +1,46 @@
24556+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
24557+
24558+include ${src}/magic.mk
24559+ifeq (${CONFIG_AUFS_FS},m)
24560+include ${src}/conf.mk
24561+endif
24562+-include ${src}/priv_def.mk
24563+
24564+# cf. include/linux/kernel.h
24565+# enable pr_debug
24566+ccflags-y += -DDEBUG
f6c5ef8b
AM
24567+# sparse requires the full pathname
24568+ifdef M
523b37e3 24569+ccflags-y += -include ${M}/../../include/uapi/linux/aufs_type.h
f6c5ef8b 24570+else
523b37e3 24571+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h
f6c5ef8b 24572+endif
4a4d8108
AM
24573+
24574+obj-$(CONFIG_AUFS_FS) += aufs.o
24575+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
24576+ wkq.o vfsub.o dcsub.o \
e49829fe 24577+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
24578+ dinfo.o dentry.o \
24579+ dynop.o \
24580+ finfo.o file.o f_op.o \
24581+ dir.o vdir.o \
24582+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
c2b27bf2 24583+ mvdown.o ioctl.o
4a4d8108
AM
24584+
24585+# all are boolean
e49829fe 24586+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
24587+aufs-$(CONFIG_SYSFS) += sysfs.o
24588+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
24589+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
24590+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
24591+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108 24592+aufs-$(CONFIG_AUFS_EXPORT) += export.o
c1595e42
JR
24593+aufs-$(CONFIG_AUFS_XATTR) += xattr.o
24594+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
8b6a4947 24595+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o
076b876e 24596+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o
4a4d8108
AM
24597+aufs-$(CONFIG_AUFS_POLL) += poll.o
24598+aufs-$(CONFIG_AUFS_RDU) += rdu.o
4a4d8108
AM
24599+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
24600+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
24601+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10 24602diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
eca34b5c
AM
24603--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
24604+++ linux/fs/aufs/module.c 2019-07-11 15:42:14.468904634 +0200
062440b3 24605@@ -0,0 +1,273 @@
cd7a4cd9 24606+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24607+/*
ba1aed25 24608+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 24609+ *
24610+ * This program, aufs is free software; you can redistribute it and/or modify
24611+ * it under the terms of the GNU General Public License as published by
24612+ * the Free Software Foundation; either version 2 of the License, or
24613+ * (at your option) any later version.
dece6358
AM
24614+ *
24615+ * This program is distributed in the hope that it will be useful,
24616+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24617+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24618+ * GNU General Public License for more details.
24619+ *
24620+ * You should have received a copy of the GNU General Public License
523b37e3 24621+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24622+ */
24623+
24624+/*
24625+ * module global variables and operations
24626+ */
24627+
24628+#include <linux/module.h>
24629+#include <linux/seq_file.h>
24630+#include "aufs.h"
24631+
e2f27e51
AM
24632+/* shrinkable realloc */
24633+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink)
1facf9fc 24634+{
e2f27e51
AM
24635+ size_t sz;
24636+ int diff;
1facf9fc 24637+
e2f27e51
AM
24638+ sz = 0;
24639+ diff = -1;
24640+ if (p) {
24641+#if 0 /* unused */
24642+ if (!new_sz) {
9f237c51 24643+ au_kfree_rcu(p);
e2f27e51
AM
24644+ p = NULL;
24645+ goto out;
24646+ }
24647+#else
24648+ AuDebugOn(!new_sz);
24649+#endif
24650+ sz = ksize(p);
24651+ diff = au_kmidx_sub(sz, new_sz);
24652+ }
24653+ if (sz && !diff)
24654+ goto out;
24655+
24656+ if (sz < new_sz)
24657+ /* expand or SLOB */
24658+ p = krealloc(p, new_sz, gfp);
24659+ else if (new_sz < sz && may_shrink) {
24660+ /* shrink */
24661+ void *q;
24662+
24663+ q = kmalloc(new_sz, gfp);
24664+ if (q) {
24665+ if (p) {
24666+ memcpy(q, p, new_sz);
9f237c51 24667+ au_kfree_try_rcu(p);
e2f27e51
AM
24668+ }
24669+ p = q;
24670+ } else
24671+ p = NULL;
24672+ }
24673+
24674+out:
24675+ return p;
24676+}
24677+
24678+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24679+ int may_shrink)
24680+{
24681+ p = au_krealloc(p, new_sz, gfp, may_shrink);
24682+ if (p && new_sz > nused)
1facf9fc 24683+ memset(p + nused, 0, new_sz - nused);
24684+ return p;
24685+}
24686+
24687+/* ---------------------------------------------------------------------- */
1facf9fc 24688+/*
24689+ * aufs caches
24690+ */
1c60b727 24691+struct kmem_cache *au_cache[AuCache_Last];
5afbbe0d
AM
24692+
24693+static void au_cache_fin(void)
24694+{
24695+ int i;
24696+
24697+ /*
24698+ * Make sure all delayed rcu free inodes are flushed before we
24699+ * destroy cache.
24700+ */
24701+ rcu_barrier();
24702+
24703+ /* excluding AuCache_HNOTIFY */
24704+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
24705+ for (i = 0; i < AuCache_HNOTIFY; i++) {
1c60b727
AM
24706+ kmem_cache_destroy(au_cache[i]);
24707+ au_cache[i] = NULL;
5afbbe0d
AM
24708+ }
24709+}
24710+
1facf9fc 24711+static int __init au_cache_init(void)
24712+{
1c60b727
AM
24713+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
24714+ if (au_cache[AuCache_DINFO])
027c5e7a 24715+ /* SLAB_DESTROY_BY_RCU */
1c60b727 24716+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
f0c0a007 24717+ au_icntnr_init_once);
1c60b727
AM
24718+ if (au_cache[AuCache_ICNTNR])
24719+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo,
f0c0a007 24720+ au_fi_init_once);
1c60b727
AM
24721+ if (au_cache[AuCache_FINFO])
24722+ au_cache[AuCache_VDIR] = AuCache(au_vdir);
24723+ if (au_cache[AuCache_VDIR])
24724+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
24725+ if (au_cache[AuCache_DEHSTR])
1facf9fc 24726+ return 0;
24727+
5afbbe0d 24728+ au_cache_fin();
1facf9fc 24729+ return -ENOMEM;
24730+}
24731+
1facf9fc 24732+/* ---------------------------------------------------------------------- */
24733+
24734+int au_dir_roflags;
24735+
e49829fe 24736+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
24737+/*
24738+ * iterate_supers_type() doesn't protect us from
24739+ * remounting (branch management)
24740+ */
8b6a4947 24741+struct hlist_bl_head au_sbilist;
e49829fe
JR
24742+#endif
24743+
1facf9fc 24744+/*
24745+ * functions for module interface.
24746+ */
24747+MODULE_LICENSE("GPL");
24748+/* MODULE_LICENSE("GPL v2"); */
dece6358 24749+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 24750+MODULE_DESCRIPTION(AUFS_NAME
24751+ " -- Advanced multi layered unification filesystem");
24752+MODULE_VERSION(AUFS_VERSION);
c06a8ce3 24753+MODULE_ALIAS_FS(AUFS_NAME);
1facf9fc 24754+
1facf9fc 24755+/* this module parameter has no meaning when SYSFS is disabled */
24756+int sysaufs_brs = 1;
24757+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
cd7a4cd9 24758+module_param_named(brs, sysaufs_brs, int, 0444);
1facf9fc 24759+
076b876e 24760+/* this module parameter has no meaning when USER_NS is disabled */
8cdd5066 24761+bool au_userns;
076b876e 24762+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns");
cd7a4cd9 24763+module_param_named(allow_userns, au_userns, bool, 0444);
076b876e 24764+
1facf9fc 24765+/* ---------------------------------------------------------------------- */
24766+
24767+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
24768+
24769+int au_seq_path(struct seq_file *seq, struct path *path)
24770+{
79b8bda9
AM
24771+ int err;
24772+
24773+ err = seq_path(seq, path, au_esc_chars);
1c60b727 24774+ if (err >= 0)
79b8bda9 24775+ err = 0;
1c60b727 24776+ else
79b8bda9
AM
24777+ err = -ENOMEM;
24778+
24779+ return err;
1facf9fc 24780+}
24781+
24782+/* ---------------------------------------------------------------------- */
24783+
24784+static int __init aufs_init(void)
24785+{
24786+ int err, i;
24787+ char *p;
24788+
24789+ p = au_esc_chars;
24790+ for (i = 1; i <= ' '; i++)
24791+ *p++ = i;
24792+ *p++ = '\\';
24793+ *p++ = '\x7f';
24794+ *p = 0;
24795+
24796+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
24797+
b95c5147
AM
24798+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop));
24799+ for (i = 0; i < AuIop_Last; i++)
24800+ aufs_iop_nogetattr[i].getattr = NULL;
24801+
1c60b727 24802+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */
f0c0a007 24803+
e49829fe 24804+ au_sbilist_init();
1facf9fc 24805+ sysaufs_brs_init();
24806+ au_debug_init();
4a4d8108 24807+ au_dy_init();
1facf9fc 24808+ err = sysaufs_init();
24809+ if (unlikely(err))
24810+ goto out;
062440b3 24811+ err = dbgaufs_init();
4f0767ce 24812+ if (unlikely(err))
953406b4 24813+ goto out_sysaufs;
062440b3
AM
24814+ err = au_procfs_init();
24815+ if (unlikely(err))
24816+ goto out_dbgaufs;
e49829fe
JR
24817+ err = au_wkq_init();
24818+ if (unlikely(err))
24819+ goto out_procfs;
87a755f4 24820+ err = au_loopback_init();
1facf9fc 24821+ if (unlikely(err))
24822+ goto out_wkq;
87a755f4
AM
24823+ err = au_hnotify_init();
24824+ if (unlikely(err))
24825+ goto out_loopback;
1facf9fc 24826+ err = au_sysrq_init();
24827+ if (unlikely(err))
24828+ goto out_hin;
24829+ err = au_cache_init();
24830+ if (unlikely(err))
24831+ goto out_sysrq;
076b876e
AM
24832+
24833+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0;
1facf9fc 24834+ err = register_filesystem(&aufs_fs_type);
24835+ if (unlikely(err))
24836+ goto out_cache;
076b876e 24837+
4a4d8108
AM
24838+ /* since we define pr_fmt, call printk directly */
24839+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 24840+ goto out; /* success */
24841+
4f0767ce 24842+out_cache:
1facf9fc 24843+ au_cache_fin();
4f0767ce 24844+out_sysrq:
1facf9fc 24845+ au_sysrq_fin();
4f0767ce 24846+out_hin:
4a4d8108 24847+ au_hnotify_fin();
87a755f4
AM
24848+out_loopback:
24849+ au_loopback_fin();
4f0767ce 24850+out_wkq:
1facf9fc 24851+ au_wkq_fin();
e49829fe
JR
24852+out_procfs:
24853+ au_procfs_fin();
062440b3
AM
24854+out_dbgaufs:
24855+ dbgaufs_fin();
4f0767ce 24856+out_sysaufs:
1facf9fc 24857+ sysaufs_fin();
4a4d8108 24858+ au_dy_fin();
4f0767ce 24859+out:
1facf9fc 24860+ return err;
24861+}
24862+
24863+static void __exit aufs_exit(void)
24864+{
24865+ unregister_filesystem(&aufs_fs_type);
24866+ au_cache_fin();
24867+ au_sysrq_fin();
4a4d8108 24868+ au_hnotify_fin();
87a755f4 24869+ au_loopback_fin();
1facf9fc 24870+ au_wkq_fin();
e49829fe 24871+ au_procfs_fin();
062440b3 24872+ dbgaufs_fin();
1facf9fc 24873+ sysaufs_fin();
4a4d8108 24874+ au_dy_fin();
1facf9fc 24875+}
24876+
24877+module_init(aufs_init);
24878+module_exit(aufs_exit);
7f207e10 24879diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
eca34b5c
AM
24880--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
24881+++ linux/fs/aufs/module.h 2019-07-11 15:42:14.468904634 +0200
9f237c51 24882@@ -0,0 +1,166 @@
062440b3 24883+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24884+/*
ba1aed25 24885+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 24886+ *
24887+ * This program, aufs is free software; you can redistribute it and/or modify
24888+ * it under the terms of the GNU General Public License as published by
24889+ * the Free Software Foundation; either version 2 of the License, or
24890+ * (at your option) any later version.
dece6358
AM
24891+ *
24892+ * This program is distributed in the hope that it will be useful,
24893+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24894+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24895+ * GNU General Public License for more details.
24896+ *
24897+ * You should have received a copy of the GNU General Public License
523b37e3 24898+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24899+ */
24900+
24901+/*
24902+ * module initialization and module-global
24903+ */
24904+
24905+#ifndef __AUFS_MODULE_H__
24906+#define __AUFS_MODULE_H__
24907+
24908+#ifdef __KERNEL__
24909+
24910+#include <linux/slab.h>
9f237c51
AM
24911+#include "debug.h"
24912+#include "dentry.h"
24913+#include "dir.h"
24914+#include "file.h"
24915+#include "inode.h"
1facf9fc 24916+
dece6358
AM
24917+struct path;
24918+struct seq_file;
24919+
1facf9fc 24920+/* module parameters */
1facf9fc 24921+extern int sysaufs_brs;
8cdd5066 24922+extern bool au_userns;
1facf9fc 24923+
24924+/* ---------------------------------------------------------------------- */
24925+
24926+extern int au_dir_roflags;
24927+
e2f27e51
AM
24928+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink);
24929+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24930+ int may_shrink);
24931+
9f237c51
AM
24932+/*
24933+ * Comparing the size of the object with sizeof(struct rcu_head)
24934+ * case 1: object is always larger
24935+ * --> au_kfree_rcu() or au_kfree_do_rcu()
24936+ * case 2: object is always smaller
24937+ * --> au_kfree_small()
24938+ * case 3: object can be any size
24939+ * --> au_kfree_try_rcu()
24940+ */
24941+
24942+static inline void au_kfree_do_rcu(const void *p)
24943+{
24944+ struct {
24945+ struct rcu_head rcu;
24946+ } *a = (void *)p;
24947+
24948+ kfree_rcu(a, rcu);
24949+}
24950+
24951+#define au_kfree_rcu(_p) do { \
24952+ typeof(_p) p = (_p); \
24953+ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \
24954+ if (p) \
24955+ au_kfree_do_rcu(p); \
24956+ } while (0)
24957+
24958+#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head))
24959+#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p)))
24960+
24961+static inline void au_kfree_try_rcu(const void *p)
24962+{
24963+ if (!p)
24964+ return;
24965+ if (au_kfree_sz_test(p))
24966+ au_kfree_do_rcu(p);
24967+ else
24968+ kfree(p);
24969+}
24970+
24971+static inline void au_kfree_small(const void *p)
24972+{
24973+ if (!p)
24974+ return;
24975+ AuDebugOn(au_kfree_sz_test(p));
24976+ kfree(p);
24977+}
24978+
e2f27e51
AM
24979+static inline int au_kmidx_sub(size_t sz, size_t new_sz)
24980+{
24981+#ifndef CONFIG_SLOB
24982+ return kmalloc_index(sz) - kmalloc_index(new_sz);
24983+#else
24984+ return -1; /* SLOB is untested */
24985+#endif
24986+}
24987+
1facf9fc 24988+int au_seq_path(struct seq_file *seq, struct path *path);
24989+
e49829fe
JR
24990+#ifdef CONFIG_PROC_FS
24991+/* procfs.c */
24992+int __init au_procfs_init(void);
24993+void au_procfs_fin(void);
24994+#else
24995+AuStubInt0(au_procfs_init, void);
24996+AuStubVoid(au_procfs_fin, void);
24997+#endif
24998+
4f0767ce
JR
24999+/* ---------------------------------------------------------------------- */
25000+
1c60b727 25001+/* kmem cache */
1facf9fc 25002+enum {
25003+ AuCache_DINFO,
25004+ AuCache_ICNTNR,
25005+ AuCache_FINFO,
25006+ AuCache_VDIR,
25007+ AuCache_DEHSTR,
7eafdf33 25008+ AuCache_HNOTIFY, /* must be last */
1facf9fc 25009+ AuCache_Last
25010+};
25011+
1c60b727 25012+extern struct kmem_cache *au_cache[AuCache_Last];
f0c0a007 25013+
4a4d8108
AM
25014+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
25015+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
25016+#define AuCacheCtor(type, ctor) \
25017+ kmem_cache_create(#type, sizeof(struct type), \
25018+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 25019+
9f237c51
AM
25020+#define AuCacheFuncs(name, index) \
25021+ static inline struct au_##name *au_cache_alloc_##name(void) \
25022+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \
25023+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \
25024+ { kmem_cache_free(au_cache[AuCache_##index], p); } \
25025+ \
25026+ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \
25027+ { void *p = rcu; \
25028+ p -= offsetof(struct au_##name, rcu); \
25029+ kmem_cache_free(au_cache[AuCache_##index], p); } \
25030+ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \
25031+ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \
25032+ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \
25033+ \
25034+ static inline void au_cache_free_##name(struct au_##name *p) \
25035+ { /* au_cache_free_##name##_norcu(p); */ \
25036+ au_cache_free_##name##_rcu(p); }
1facf9fc 25037+
25038+AuCacheFuncs(dinfo, DINFO);
25039+AuCacheFuncs(icntnr, ICNTNR);
25040+AuCacheFuncs(finfo, FINFO);
25041+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
25042+AuCacheFuncs(vdir_dehstr, DEHSTR);
25043+#ifdef CONFIG_AUFS_HNOTIFY
25044+AuCacheFuncs(hnotify, HNOTIFY);
25045+#endif
1facf9fc 25046+
4a4d8108
AM
25047+#endif /* __KERNEL__ */
25048+#endif /* __AUFS_MODULE_H__ */
c2b27bf2 25049diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
eca34b5c
AM
25050--- /usr/share/empty/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100
25051+++ linux/fs/aufs/mvdown.c 2019-07-11 15:42:14.472238057 +0200
ba1aed25 25052@@ -0,0 +1,706 @@
cd7a4cd9 25053+// SPDX-License-Identifier: GPL-2.0
c2b27bf2 25054+/*
ba1aed25 25055+ * Copyright (C) 2011-2019 Junjiro R. Okajima
c2b27bf2
AM
25056+ *
25057+ * This program, aufs is free software; you can redistribute it and/or modify
25058+ * it under the terms of the GNU General Public License as published by
25059+ * the Free Software Foundation; either version 2 of the License, or
25060+ * (at your option) any later version.
25061+ *
25062+ * This program is distributed in the hope that it will be useful,
25063+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25064+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25065+ * GNU General Public License for more details.
25066+ *
25067+ * You should have received a copy of the GNU General Public License
523b37e3
AM
25068+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
25069+ */
25070+
25071+/*
25072+ * move-down, opposite of copy-up
c2b27bf2
AM
25073+ */
25074+
25075+#include "aufs.h"
25076+
c2b27bf2
AM
25077+struct au_mvd_args {
25078+ struct {
c2b27bf2
AM
25079+ struct super_block *h_sb;
25080+ struct dentry *h_parent;
25081+ struct au_hinode *hdir;
392086de 25082+ struct inode *h_dir, *h_inode;
c1595e42 25083+ struct au_pin pin;
c2b27bf2
AM
25084+ } info[AUFS_MVDOWN_NARRAY];
25085+
25086+ struct aufs_mvdown mvdown;
25087+ struct dentry *dentry, *parent;
25088+ struct inode *inode, *dir;
25089+ struct super_block *sb;
25090+ aufs_bindex_t bopq, bwh, bfound;
25091+ unsigned char rename_lock;
c2b27bf2
AM
25092+};
25093+
392086de 25094+#define mvd_errno mvdown.au_errno
076b876e
AM
25095+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex
25096+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid
25097+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex
25098+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid
c2b27bf2 25099+
392086de
AM
25100+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb
25101+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent
25102+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir
25103+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir
25104+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode
c1595e42 25105+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin
392086de
AM
25106+
25107+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb
25108+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent
25109+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir
25110+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir
25111+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode
c1595e42 25112+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin
c2b27bf2
AM
25113+
25114+#define AU_MVD_PR(flag, ...) do { \
25115+ if (flag) \
25116+ pr_err(__VA_ARGS__); \
25117+ } while (0)
25118+
076b876e
AM
25119+static int find_lower_writable(struct au_mvd_args *a)
25120+{
25121+ struct super_block *sb;
5afbbe0d 25122+ aufs_bindex_t bindex, bbot;
076b876e
AM
25123+ struct au_branch *br;
25124+
25125+ sb = a->sb;
25126+ bindex = a->mvd_bsrc;
5afbbe0d 25127+ bbot = au_sbbot(sb);
076b876e 25128+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER)
5afbbe0d 25129+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
25130+ br = au_sbr(sb, bindex);
25131+ if (au_br_fhsm(br->br_perm)
8b6a4947 25132+ && !sb_rdonly(au_br_sb(br)))
076b876e
AM
25133+ return bindex;
25134+ }
25135+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER))
5afbbe0d 25136+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
25137+ br = au_sbr(sb, bindex);
25138+ if (!au_br_rdonly(br))
25139+ return bindex;
25140+ }
25141+ else
5afbbe0d 25142+ for (bindex++; bindex <= bbot; bindex++) {
076b876e 25143+ br = au_sbr(sb, bindex);
8b6a4947 25144+ if (!sb_rdonly(au_br_sb(br))) {
076b876e
AM
25145+ if (au_br_rdonly(br))
25146+ a->mvdown.flags
25147+ |= AUFS_MVDOWN_ROLOWER_R;
25148+ return bindex;
25149+ }
25150+ }
25151+
25152+ return -1;
25153+}
25154+
c2b27bf2 25155+/* make the parent dir on bdst */
392086de 25156+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25157+{
25158+ int err;
25159+
25160+ err = 0;
25161+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc);
25162+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst);
25163+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc);
25164+ a->mvd_h_dst_parent = NULL;
5afbbe0d 25165+ if (au_dbbot(a->parent) >= a->mvd_bdst)
c2b27bf2
AM
25166+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
25167+ if (!a->mvd_h_dst_parent) {
25168+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst);
25169+ if (unlikely(err)) {
392086de 25170+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n");
c2b27bf2
AM
25171+ goto out;
25172+ }
25173+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
25174+ }
25175+
25176+out:
25177+ AuTraceErr(err);
25178+ return err;
25179+}
25180+
25181+/* lock them all */
392086de 25182+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25183+{
25184+ int err;
25185+ struct dentry *h_trap;
25186+
25187+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
25188+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
c1595e42
JR
25189+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
25190+ au_opt_udba(a->sb),
25191+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25192+ AuTraceErr(err);
25193+ if (unlikely(err)) {
25194+ AU_MVD_PR(dmsg, "pin_dst failed\n");
25195+ goto out;
25196+ }
25197+
c2b27bf2
AM
25198+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
25199+ a->rename_lock = 0;
c1595e42
JR
25200+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25201+ AuLsc_DI_PARENT, AuLsc_I_PARENT3,
25202+ au_opt_udba(a->sb),
25203+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25204+ err = au_do_pin(&a->mvd_pin_src);
25205+ AuTraceErr(err);
5527c038 25206+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25207+ if (unlikely(err)) {
25208+ AU_MVD_PR(dmsg, "pin_src failed\n");
25209+ goto out_dst;
25210+ }
25211+ goto out; /* success */
c2b27bf2
AM
25212+ }
25213+
c2b27bf2 25214+ a->rename_lock = 1;
c1595e42
JR
25215+ au_pin_hdir_unlock(&a->mvd_pin_dst);
25216+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25217+ au_opt_udba(a->sb),
25218+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25219+ AuTraceErr(err);
5527c038 25220+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25221+ if (unlikely(err)) {
25222+ AU_MVD_PR(dmsg, "pin_src failed\n");
25223+ au_pin_hdir_lock(&a->mvd_pin_dst);
25224+ goto out_dst;
25225+ }
25226+ au_pin_hdir_unlock(&a->mvd_pin_src);
c2b27bf2
AM
25227+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25228+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25229+ if (h_trap) {
25230+ err = (h_trap != a->mvd_h_src_parent);
25231+ if (err)
25232+ err = (h_trap != a->mvd_h_dst_parent);
25233+ }
25234+ BUG_ON(err); /* it should never happen */
c1595e42
JR
25235+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
25236+ err = -EBUSY;
25237+ AuTraceErr(err);
25238+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25239+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25240+ au_pin_hdir_lock(&a->mvd_pin_src);
25241+ au_unpin(&a->mvd_pin_src);
25242+ au_pin_hdir_lock(&a->mvd_pin_dst);
25243+ goto out_dst;
25244+ }
25245+ goto out; /* success */
c2b27bf2 25246+
c1595e42
JR
25247+out_dst:
25248+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25249+out:
25250+ AuTraceErr(err);
25251+ return err;
25252+}
25253+
392086de 25254+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2 25255+{
c1595e42
JR
25256+ if (!a->rename_lock)
25257+ au_unpin(&a->mvd_pin_src);
25258+ else {
c2b27bf2
AM
25259+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25260+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
c1595e42
JR
25261+ au_pin_hdir_lock(&a->mvd_pin_src);
25262+ au_unpin(&a->mvd_pin_src);
25263+ au_pin_hdir_lock(&a->mvd_pin_dst);
25264+ }
25265+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25266+}
25267+
25268+/* copy-down the file */
392086de 25269+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25270+{
25271+ int err;
25272+ struct au_cp_generic cpg = {
25273+ .dentry = a->dentry,
25274+ .bdst = a->mvd_bdst,
25275+ .bsrc = a->mvd_bsrc,
25276+ .len = -1,
c1595e42 25277+ .pin = &a->mvd_pin_dst,
c2b27bf2
AM
25278+ .flags = AuCpup_DTIME | AuCpup_HOPEN
25279+ };
25280+
25281+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
392086de
AM
25282+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25283+ au_fset_cpup(cpg.flags, OVERWRITE);
25284+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER)
25285+ au_fset_cpup(cpg.flags, RWDST);
c2b27bf2
AM
25286+ err = au_sio_cpdown_simple(&cpg);
25287+ if (unlikely(err))
392086de 25288+ AU_MVD_PR(dmsg, "cpdown failed\n");
c2b27bf2
AM
25289+
25290+ AuTraceErr(err);
25291+ return err;
25292+}
25293+
25294+/*
25295+ * unlink the whiteout on bdst if exist which may be created by UDBA while we
25296+ * were sleeping
25297+ */
392086de 25298+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25299+{
25300+ int err;
25301+ struct path h_path;
25302+ struct au_branch *br;
523b37e3 25303+ struct inode *delegated;
c2b27bf2
AM
25304+
25305+ br = au_sbr(a->sb, a->mvd_bdst);
25306+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
25307+ err = PTR_ERR(h_path.dentry);
25308+ if (IS_ERR(h_path.dentry)) {
392086de 25309+ AU_MVD_PR(dmsg, "wh_lkup failed\n");
c2b27bf2
AM
25310+ goto out;
25311+ }
25312+
25313+ err = 0;
5527c038 25314+ if (d_is_positive(h_path.dentry)) {
c2b27bf2 25315+ h_path.mnt = au_br_mnt(br);
523b37e3 25316+ delegated = NULL;
5527c038 25317+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path,
523b37e3
AM
25318+ &delegated, /*force*/0);
25319+ if (unlikely(err == -EWOULDBLOCK)) {
25320+ pr_warn("cannot retry for NFSv4 delegation"
25321+ " for an internal unlink\n");
25322+ iput(delegated);
25323+ }
c2b27bf2 25324+ if (unlikely(err))
392086de 25325+ AU_MVD_PR(dmsg, "wh_unlink failed\n");
c2b27bf2
AM
25326+ }
25327+ dput(h_path.dentry);
25328+
25329+out:
25330+ AuTraceErr(err);
25331+ return err;
25332+}
25333+
25334+/*
25335+ * unlink the topmost h_dentry
c2b27bf2 25336+ */
392086de 25337+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25338+{
25339+ int err;
25340+ struct path h_path;
523b37e3 25341+ struct inode *delegated;
c2b27bf2
AM
25342+
25343+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc);
25344+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc);
523b37e3
AM
25345+ delegated = NULL;
25346+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0);
25347+ if (unlikely(err == -EWOULDBLOCK)) {
25348+ pr_warn("cannot retry for NFSv4 delegation"
25349+ " for an internal unlink\n");
25350+ iput(delegated);
25351+ }
c2b27bf2 25352+ if (unlikely(err))
392086de 25353+ AU_MVD_PR(dmsg, "unlink failed\n");
c2b27bf2
AM
25354+
25355+ AuTraceErr(err);
25356+ return err;
25357+}
25358+
076b876e
AM
25359+/* Since mvdown succeeded, we ignore an error of this function */
25360+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a)
25361+{
25362+ int err;
25363+ struct au_branch *br;
25364+
25365+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED;
25366+ br = au_sbr(a->sb, a->mvd_bsrc);
25367+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs);
25368+ if (!err) {
25369+ br = au_sbr(a->sb, a->mvd_bdst);
25370+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id;
25371+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs);
25372+ }
25373+ if (!err)
25374+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED;
25375+ else
25376+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err);
25377+}
25378+
c2b27bf2
AM
25379+/*
25380+ * copy-down the file and unlink the bsrc file.
25381+ * - unlink the bdst whout if exist
25382+ * - copy-down the file (with whtmp name and rename)
25383+ * - unlink the bsrc file
25384+ */
392086de 25385+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25386+{
25387+ int err;
25388+
392086de 25389+ err = au_do_mkdir(dmsg, a);
c2b27bf2 25390+ if (!err)
392086de 25391+ err = au_do_lock(dmsg, a);
c2b27bf2
AM
25392+ if (unlikely(err))
25393+ goto out;
25394+
25395+ /*
25396+ * do not revert the activities we made on bdst since they should be
25397+ * harmless in aufs.
25398+ */
25399+
392086de 25400+ err = au_do_cpdown(dmsg, a);
c2b27bf2 25401+ if (!err)
392086de
AM
25402+ err = au_do_unlink_wh(dmsg, a);
25403+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
25404+ err = au_do_unlink(dmsg, a);
c2b27bf2
AM
25405+ if (unlikely(err))
25406+ goto out_unlock;
25407+
c1595e42
JR
25408+ AuDbg("%pd2, 0x%x, %d --> %d\n",
25409+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
076b876e
AM
25410+ if (find_lower_writable(a) < 0)
25411+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;
25412+
25413+ if (a->mvdown.flags & AUFS_MVDOWN_STFS)
25414+ au_do_stfs(dmsg, a);
25415+
c2b27bf2 25416+ /* maintain internal array */
392086de
AM
25417+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
25418+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
5afbbe0d 25419+ au_set_dbtop(a->dentry, a->mvd_bdst);
392086de 25420+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
5afbbe0d 25421+ au_set_ibtop(a->inode, a->mvd_bdst);
79b8bda9
AM
25422+ } else {
25423+ /* hide the lower */
25424+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
5afbbe0d 25425+ au_set_dbbot(a->dentry, a->mvd_bsrc);
79b8bda9 25426+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
5afbbe0d 25427+ au_set_ibbot(a->inode, a->mvd_bsrc);
392086de 25428+ }
5afbbe0d
AM
25429+ if (au_dbbot(a->dentry) < a->mvd_bdst)
25430+ au_set_dbbot(a->dentry, a->mvd_bdst);
25431+ if (au_ibbot(a->inode) < a->mvd_bdst)
25432+ au_set_ibbot(a->inode, a->mvd_bdst);
c2b27bf2
AM
25433+
25434+out_unlock:
392086de 25435+ au_do_unlock(dmsg, a);
c2b27bf2
AM
25436+out:
25437+ AuTraceErr(err);
25438+ return err;
25439+}
25440+
25441+/* ---------------------------------------------------------------------- */
25442+
c2b27bf2 25443+/* make sure the file is idle */
392086de 25444+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25445+{
25446+ int err, plinked;
c2b27bf2
AM
25447+
25448+ err = 0;
c2b27bf2 25449+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
5afbbe0d 25450+ if (au_dbtop(a->dentry) == a->mvd_bsrc
c1595e42 25451+ && au_dcount(a->dentry) == 1
c2b27bf2 25452+ && atomic_read(&a->inode->i_count) == 1
392086de 25453+ /* && a->mvd_h_src_inode->i_nlink == 1 */
c2b27bf2
AM
25454+ && (!plinked || !au_plink_test(a->inode))
25455+ && a->inode->i_nlink == 1)
25456+ goto out;
25457+
25458+ err = -EBUSY;
392086de 25459+ AU_MVD_PR(dmsg,
c1595e42 25460+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
5afbbe0d 25461+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry),
c2b27bf2 25462+ atomic_read(&a->inode->i_count), a->inode->i_nlink,
392086de 25463+ a->mvd_h_src_inode->i_nlink,
c2b27bf2
AM
25464+ plinked, plinked ? au_plink_test(a->inode) : 0);
25465+
25466+out:
25467+ AuTraceErr(err);
25468+ return err;
25469+}
25470+
25471+/* make sure the parent dir is fine */
392086de 25472+static int au_mvd_args_parent(const unsigned char dmsg,
c2b27bf2
AM
25473+ struct au_mvd_args *a)
25474+{
25475+ int err;
25476+ aufs_bindex_t bindex;
25477+
25478+ err = 0;
25479+ if (unlikely(au_alive_dir(a->parent))) {
25480+ err = -ENOENT;
392086de 25481+ AU_MVD_PR(dmsg, "parent dir is dead\n");
c2b27bf2
AM
25482+ goto out;
25483+ }
25484+
25485+ a->bopq = au_dbdiropq(a->parent);
25486+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
25487+ AuDbg("b%d\n", bindex);
25488+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
25489+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
25490+ err = -EINVAL;
392086de
AM
25491+ a->mvd_errno = EAU_MVDOWN_OPAQUE;
25492+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n",
c2b27bf2
AM
25493+ a->bopq, a->mvd_bdst);
25494+ }
25495+
25496+out:
25497+ AuTraceErr(err);
25498+ return err;
25499+}
25500+
392086de 25501+static int au_mvd_args_intermediate(const unsigned char dmsg,
c2b27bf2
AM
25502+ struct au_mvd_args *a)
25503+{
25504+ int err;
25505+ struct au_dinfo *dinfo, *tmp;
25506+
25507+ /* lookup the next lower positive entry */
25508+ err = -ENOMEM;
25509+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP);
25510+ if (unlikely(!tmp))
25511+ goto out;
25512+
25513+ a->bfound = -1;
25514+ a->bwh = -1;
25515+ dinfo = au_di(a->dentry);
25516+ au_di_cp(tmp, dinfo);
25517+ au_di_swap(tmp, dinfo);
25518+
25519+ /* returns the number of positive dentries */
5afbbe0d
AM
25520+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1,
25521+ /* AuLkup_IGNORE_PERM */ 0);
c2b27bf2
AM
25522+ if (!err)
25523+ a->bwh = au_dbwh(a->dentry);
25524+ else if (err > 0)
5afbbe0d 25525+ a->bfound = au_dbtop(a->dentry);
c2b27bf2
AM
25526+
25527+ au_di_swap(tmp, dinfo);
25528+ au_rw_write_unlock(&tmp->di_rwsem);
25529+ au_di_free(tmp);
25530+ if (unlikely(err < 0))
392086de 25531+ AU_MVD_PR(dmsg, "failed look-up lower\n");
c2b27bf2
AM
25532+
25533+ /*
25534+ * here, we have these cases.
25535+ * bfound == -1
25536+ * no positive dentry under bsrc. there are more sub-cases.
25537+ * bwh < 0
25538+ * there no whiteout, we can safely move-down.
25539+ * bwh <= bsrc
25540+ * impossible
25541+ * bsrc < bwh && bwh < bdst
25542+ * there is a whiteout on RO branch. cannot proceed.
25543+ * bwh == bdst
25544+ * there is a whiteout on the RW target branch. it should
25545+ * be removed.
25546+ * bdst < bwh
25547+ * there is a whiteout somewhere unrelated branch.
25548+ * -1 < bfound && bfound <= bsrc
25549+ * impossible.
25550+ * bfound < bdst
25551+ * found, but it is on RO branch between bsrc and bdst. cannot
25552+ * proceed.
25553+ * bfound == bdst
25554+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return
25555+ * error.
25556+ * bdst < bfound
25557+ * found, after we create the file on bdst, it will be hidden.
25558+ */
25559+
25560+ AuDebugOn(a->bfound == -1
25561+ && a->bwh != -1
25562+ && a->bwh <= a->mvd_bsrc);
25563+ AuDebugOn(-1 < a->bfound
25564+ && a->bfound <= a->mvd_bsrc);
25565+
25566+ err = -EINVAL;
25567+ if (a->bfound == -1
25568+ && a->mvd_bsrc < a->bwh
25569+ && a->bwh != -1
25570+ && a->bwh < a->mvd_bdst) {
392086de
AM
25571+ a->mvd_errno = EAU_MVDOWN_WHITEOUT;
25572+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n",
c2b27bf2
AM
25573+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh);
25574+ goto out;
25575+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) {
392086de
AM
25576+ a->mvd_errno = EAU_MVDOWN_UPPER;
25577+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n",
c2b27bf2
AM
25578+ a->mvd_bdst, a->bfound);
25579+ goto out;
25580+ }
25581+
25582+ err = 0; /* success */
25583+
25584+out:
25585+ AuTraceErr(err);
25586+ return err;
25587+}
25588+
392086de 25589+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25590+{
25591+ int err;
25592+
392086de
AM
25593+ err = 0;
25594+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25595+ && a->bfound == a->mvd_bdst)
25596+ err = -EEXIST;
c2b27bf2
AM
25597+ AuTraceErr(err);
25598+ return err;
25599+}
25600+
392086de 25601+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25602+{
25603+ int err;
25604+ struct au_branch *br;
25605+
25606+ err = -EISDIR;
25607+ if (unlikely(S_ISDIR(a->inode->i_mode)))
25608+ goto out;
25609+
25610+ err = -EINVAL;
392086de 25611+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER))
5afbbe0d 25612+ a->mvd_bsrc = au_ibtop(a->inode);
392086de
AM
25613+ else {
25614+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid);
25615+ if (unlikely(a->mvd_bsrc < 0
5afbbe0d
AM
25616+ || (a->mvd_bsrc < au_dbtop(a->dentry)
25617+ || au_dbbot(a->dentry) < a->mvd_bsrc
392086de 25618+ || !au_h_dptr(a->dentry, a->mvd_bsrc))
5afbbe0d
AM
25619+ || (a->mvd_bsrc < au_ibtop(a->inode)
25620+ || au_ibbot(a->inode) < a->mvd_bsrc
392086de
AM
25621+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) {
25622+ a->mvd_errno = EAU_MVDOWN_NOUPPER;
25623+ AU_MVD_PR(dmsg, "no upper\n");
25624+ goto out;
25625+ }
25626+ }
5afbbe0d 25627+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) {
392086de
AM
25628+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25629+ AU_MVD_PR(dmsg, "on the bottom\n");
c2b27bf2
AM
25630+ goto out;
25631+ }
392086de 25632+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
c2b27bf2
AM
25633+ br = au_sbr(a->sb, a->mvd_bsrc);
25634+ err = au_br_rdonly(br);
392086de
AM
25635+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) {
25636+ if (unlikely(err))
25637+ goto out;
25638+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode)
25639+ || IS_APPEND(a->mvd_h_src_inode))) {
25640+ if (err)
25641+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R;
25642+ /* go on */
25643+ } else
c2b27bf2
AM
25644+ goto out;
25645+
25646+ err = -EINVAL;
392086de
AM
25647+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) {
25648+ a->mvd_bdst = find_lower_writable(a);
25649+ if (unlikely(a->mvd_bdst < 0)) {
25650+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25651+ AU_MVD_PR(dmsg, "no writable lower branch\n");
25652+ goto out;
25653+ }
25654+ } else {
25655+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid);
25656+ if (unlikely(a->mvd_bdst < 0
5afbbe0d 25657+ || au_sbbot(a->sb) < a->mvd_bdst)) {
392086de
AM
25658+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR;
25659+ AU_MVD_PR(dmsg, "no lower brid\n");
25660+ goto out;
25661+ }
c2b27bf2
AM
25662+ }
25663+
392086de 25664+ err = au_mvd_args_busy(dmsg, a);
c2b27bf2 25665+ if (!err)
392086de 25666+ err = au_mvd_args_parent(dmsg, a);
c2b27bf2 25667+ if (!err)
392086de 25668+ err = au_mvd_args_intermediate(dmsg, a);
c2b27bf2 25669+ if (!err)
392086de 25670+ err = au_mvd_args_exist(dmsg, a);
c2b27bf2
AM
25671+ if (!err)
25672+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);
25673+
25674+out:
25675+ AuTraceErr(err);
25676+ return err;
25677+}
25678+
25679+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg)
25680+{
392086de
AM
25681+ int err, e;
25682+ unsigned char dmsg;
25683+ struct au_mvd_args *args;
79b8bda9 25684+ struct inode *inode;
c2b27bf2 25685+
79b8bda9 25686+ inode = d_inode(dentry);
c2b27bf2
AM
25687+ err = -EPERM;
25688+ if (unlikely(!capable(CAP_SYS_ADMIN)))
25689+ goto out;
25690+
392086de
AM
25691+ err = -ENOMEM;
25692+ args = kmalloc(sizeof(*args), GFP_NOFS);
25693+ if (unlikely(!args))
25694+ goto out;
25695+
25696+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown));
25697+ if (!err)
ba1aed25
AM
25698+ /* VERIFY_WRITE */
25699+ err = !access_ok(uarg, sizeof(*uarg));
c2b27bf2
AM
25700+ if (unlikely(err)) {
25701+ err = -EFAULT;
392086de
AM
25702+ AuTraceErr(err);
25703+ goto out_free;
c2b27bf2 25704+ }
392086de
AM
25705+ AuDbg("flags 0x%x\n", args->mvdown.flags);
25706+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R);
25707+ args->mvdown.au_errno = 0;
25708+ args->dentry = dentry;
79b8bda9 25709+ args->inode = inode;
392086de 25710+ args->sb = dentry->d_sb;
c2b27bf2 25711+
392086de
AM
25712+ err = -ENOENT;
25713+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG);
25714+ args->parent = dget_parent(dentry);
5527c038 25715+ args->dir = d_inode(args->parent);
febd17d6 25716+ inode_lock_nested(args->dir, I_MUTEX_PARENT);
392086de
AM
25717+ dput(args->parent);
25718+ if (unlikely(args->parent != dentry->d_parent)) {
25719+ AU_MVD_PR(dmsg, "parent dir is moved\n");
c2b27bf2
AM
25720+ goto out_dir;
25721+ }
25722+
febd17d6 25723+ inode_lock_nested(inode, I_MUTEX_CHILD);
b95c5147 25724+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW);
c2b27bf2
AM
25725+ if (unlikely(err))
25726+ goto out_inode;
25727+
392086de
AM
25728+ di_write_lock_parent(args->parent);
25729+ err = au_mvd_args(dmsg, args);
c2b27bf2
AM
25730+ if (unlikely(err))
25731+ goto out_parent;
25732+
392086de 25733+ err = au_do_mvdown(dmsg, args);
c2b27bf2
AM
25734+ if (unlikely(err))
25735+ goto out_parent;
c2b27bf2 25736+
392086de 25737+ au_cpup_attr_timesizes(args->dir);
79b8bda9
AM
25738+ au_cpup_attr_timesizes(inode);
25739+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER))
25740+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst));
c2b27bf2
AM
25741+ /* au_digen_dec(dentry); */
25742+
25743+out_parent:
392086de 25744+ di_write_unlock(args->parent);
c2b27bf2
AM
25745+ aufs_read_unlock(dentry, AuLock_DW);
25746+out_inode:
febd17d6 25747+ inode_unlock(inode);
c2b27bf2 25748+out_dir:
febd17d6 25749+ inode_unlock(args->dir);
392086de
AM
25750+out_free:
25751+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown));
25752+ if (unlikely(e))
25753+ err = -EFAULT;
9f237c51 25754+ au_kfree_rcu(args);
c2b27bf2
AM
25755+out:
25756+ AuTraceErr(err);
25757+ return err;
25758+}
25759diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
eca34b5c
AM
25760--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
25761+++ linux/fs/aufs/opts.c 2019-09-16 09:38:43.216175640 +0200
25762@@ -0,0 +1,1880 @@
cd7a4cd9 25763+// SPDX-License-Identifier: GPL-2.0
1facf9fc 25764+/*
ba1aed25 25765+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 25766+ *
25767+ * This program, aufs is free software; you can redistribute it and/or modify
25768+ * it under the terms of the GNU General Public License as published by
25769+ * the Free Software Foundation; either version 2 of the License, or
25770+ * (at your option) any later version.
dece6358
AM
25771+ *
25772+ * This program is distributed in the hope that it will be useful,
25773+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25774+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25775+ * GNU General Public License for more details.
25776+ *
25777+ * You should have received a copy of the GNU General Public License
523b37e3 25778+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 25779+ */
25780+
25781+/*
25782+ * mount options/flags
25783+ */
25784+
dece6358 25785+#include <linux/namei.h>
1facf9fc 25786+#include <linux/types.h> /* a distribution requires */
25787+#include <linux/parser.h>
25788+#include "aufs.h"
25789+
25790+/* ---------------------------------------------------------------------- */
25791+
25792+enum {
25793+ Opt_br,
7e9cd9fe
AM
25794+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
25795+ Opt_idel, Opt_imod,
25796+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
dece6358 25797+ Opt_rdblk_def, Opt_rdhash_def,
7e9cd9fe 25798+ Opt_xino, Opt_noxino,
1facf9fc 25799+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
25800+ Opt_trunc_xino_path, Opt_itrunc_xino,
25801+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 25802+ Opt_shwh, Opt_noshwh,
1facf9fc 25803+ Opt_plink, Opt_noplink, Opt_list_plink,
25804+ Opt_udba,
4a4d8108 25805+ Opt_dio, Opt_nodio,
1facf9fc 25806+ Opt_diropq_a, Opt_diropq_w,
25807+ Opt_warn_perm, Opt_nowarn_perm,
25808+ Opt_wbr_copyup, Opt_wbr_create,
076b876e 25809+ Opt_fhsm_sec,
1facf9fc 25810+ Opt_verbose, Opt_noverbose,
25811+ Opt_sum, Opt_nosum, Opt_wsum,
076b876e 25812+ Opt_dirperm1, Opt_nodirperm1,
8b6a4947 25813+ Opt_dirren, Opt_nodirren,
c1595e42 25814+ Opt_acl, Opt_noacl,
1facf9fc 25815+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
25816+};
25817+
25818+static match_table_t options = {
25819+ {Opt_br, "br=%s"},
25820+ {Opt_br, "br:%s"},
25821+
25822+ {Opt_add, "add=%d:%s"},
25823+ {Opt_add, "add:%d:%s"},
25824+ {Opt_add, "ins=%d:%s"},
25825+ {Opt_add, "ins:%d:%s"},
25826+ {Opt_append, "append=%s"},
25827+ {Opt_append, "append:%s"},
25828+ {Opt_prepend, "prepend=%s"},
25829+ {Opt_prepend, "prepend:%s"},
25830+
25831+ {Opt_del, "del=%s"},
25832+ {Opt_del, "del:%s"},
25833+ /* {Opt_idel, "idel:%d"}, */
25834+ {Opt_mod, "mod=%s"},
25835+ {Opt_mod, "mod:%s"},
25836+ /* {Opt_imod, "imod:%d:%s"}, */
25837+
25838+ {Opt_dirwh, "dirwh=%d"},
25839+
25840+ {Opt_xino, "xino=%s"},
25841+ {Opt_noxino, "noxino"},
25842+ {Opt_trunc_xino, "trunc_xino"},
25843+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
25844+ {Opt_notrunc_xino, "notrunc_xino"},
25845+ {Opt_trunc_xino_path, "trunc_xino=%s"},
25846+ {Opt_itrunc_xino, "itrunc_xino=%d"},
25847+ /* {Opt_zxino, "zxino=%s"}, */
25848+ {Opt_trunc_xib, "trunc_xib"},
25849+ {Opt_notrunc_xib, "notrunc_xib"},
25850+
e49829fe 25851+#ifdef CONFIG_PROC_FS
1facf9fc 25852+ {Opt_plink, "plink"},
e49829fe
JR
25853+#else
25854+ {Opt_ignore_silent, "plink"},
25855+#endif
25856+
1facf9fc 25857+ {Opt_noplink, "noplink"},
e49829fe 25858+
1facf9fc 25859+#ifdef CONFIG_AUFS_DEBUG
25860+ {Opt_list_plink, "list_plink"},
25861+#endif
25862+
25863+ {Opt_udba, "udba=%s"},
25864+
4a4d8108
AM
25865+ {Opt_dio, "dio"},
25866+ {Opt_nodio, "nodio"},
25867+
8b6a4947
AM
25868+#ifdef CONFIG_AUFS_DIRREN
25869+ {Opt_dirren, "dirren"},
25870+ {Opt_nodirren, "nodirren"},
25871+#else
25872+ {Opt_ignore, "dirren"},
25873+ {Opt_ignore_silent, "nodirren"},
25874+#endif
25875+
076b876e
AM
25876+#ifdef CONFIG_AUFS_FHSM
25877+ {Opt_fhsm_sec, "fhsm_sec=%d"},
25878+#else
8b6a4947 25879+ {Opt_ignore, "fhsm_sec=%d"},
076b876e
AM
25880+#endif
25881+
1facf9fc 25882+ {Opt_diropq_a, "diropq=always"},
25883+ {Opt_diropq_a, "diropq=a"},
25884+ {Opt_diropq_w, "diropq=whiteouted"},
25885+ {Opt_diropq_w, "diropq=w"},
25886+
25887+ {Opt_warn_perm, "warn_perm"},
25888+ {Opt_nowarn_perm, "nowarn_perm"},
25889+
25890+ /* keep them temporary */
1facf9fc 25891+ {Opt_ignore_silent, "nodlgt"},
8b6a4947 25892+ {Opt_ignore, "clean_plink"},
1facf9fc 25893+
dece6358
AM
25894+#ifdef CONFIG_AUFS_SHWH
25895+ {Opt_shwh, "shwh"},
25896+#endif
25897+ {Opt_noshwh, "noshwh"},
25898+
076b876e
AM
25899+ {Opt_dirperm1, "dirperm1"},
25900+ {Opt_nodirperm1, "nodirperm1"},
25901+
1facf9fc 25902+ {Opt_verbose, "verbose"},
25903+ {Opt_verbose, "v"},
25904+ {Opt_noverbose, "noverbose"},
25905+ {Opt_noverbose, "quiet"},
25906+ {Opt_noverbose, "q"},
25907+ {Opt_noverbose, "silent"},
25908+
25909+ {Opt_sum, "sum"},
25910+ {Opt_nosum, "nosum"},
25911+ {Opt_wsum, "wsum"},
25912+
25913+ {Opt_rdcache, "rdcache=%d"},
25914+ {Opt_rdblk, "rdblk=%d"},
dece6358 25915+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 25916+ {Opt_rdhash, "rdhash=%d"},
dece6358 25917+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 25918+
25919+ {Opt_wbr_create, "create=%s"},
25920+ {Opt_wbr_create, "create_policy=%s"},
25921+ {Opt_wbr_copyup, "cpup=%s"},
25922+ {Opt_wbr_copyup, "copyup=%s"},
25923+ {Opt_wbr_copyup, "copyup_policy=%s"},
25924+
c1595e42
JR
25925+ /* generic VFS flag */
25926+#ifdef CONFIG_FS_POSIX_ACL
25927+ {Opt_acl, "acl"},
25928+ {Opt_noacl, "noacl"},
25929+#else
8b6a4947 25930+ {Opt_ignore, "acl"},
c1595e42
JR
25931+ {Opt_ignore_silent, "noacl"},
25932+#endif
25933+
1facf9fc 25934+ /* internal use for the scripts */
25935+ {Opt_ignore_silent, "si=%s"},
25936+
25937+ {Opt_br, "dirs=%s"},
25938+ {Opt_ignore, "debug=%d"},
25939+ {Opt_ignore, "delete=whiteout"},
25940+ {Opt_ignore, "delete=all"},
25941+ {Opt_ignore, "imap=%s"},
25942+
1308ab2a 25943+ /* temporary workaround, due to old mount(8)? */
25944+ {Opt_ignore_silent, "relatime"},
25945+
1facf9fc 25946+ {Opt_err, NULL}
25947+};
25948+
25949+/* ---------------------------------------------------------------------- */
25950+
076b876e 25951+static const char *au_parser_pattern(int val, match_table_t tbl)
1facf9fc 25952+{
076b876e
AM
25953+ struct match_token *p;
25954+
25955+ p = tbl;
25956+ while (p->pattern) {
25957+ if (p->token == val)
25958+ return p->pattern;
25959+ p++;
1facf9fc 25960+ }
25961+ BUG();
25962+ return "??";
25963+}
25964+
076b876e
AM
25965+static const char *au_optstr(int *val, match_table_t tbl)
25966+{
25967+ struct match_token *p;
25968+ int v;
25969+
25970+ v = *val;
2000de60
JR
25971+ if (!v)
25972+ goto out;
076b876e 25973+ p = tbl;
2000de60
JR
25974+ while (p->pattern) {
25975+ if (p->token
25976+ && (v & p->token) == p->token) {
076b876e
AM
25977+ *val &= ~p->token;
25978+ return p->pattern;
25979+ }
25980+ p++;
25981+ }
2000de60
JR
25982+
25983+out:
076b876e
AM
25984+ return NULL;
25985+}
25986+
1facf9fc 25987+/* ---------------------------------------------------------------------- */
25988+
1e00d052 25989+static match_table_t brperm = {
1facf9fc 25990+ {AuBrPerm_RO, AUFS_BRPERM_RO},
25991+ {AuBrPerm_RR, AUFS_BRPERM_RR},
25992+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
25993+ {0, NULL}
25994+};
1facf9fc 25995+
86dc4139 25996+static match_table_t brattr = {
076b876e
AM
25997+ /* general */
25998+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG},
25999+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL},
c1595e42 26000+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */
86dc4139 26001+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
2000de60 26002+#ifdef CONFIG_AUFS_FHSM
076b876e 26003+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM},
2000de60
JR
26004+#endif
26005+#ifdef CONFIG_AUFS_XATTR
c1595e42
JR
26006+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX},
26007+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC},
26008+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS},
26009+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR},
26010+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR},
26011+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH},
2000de60 26012+#endif
076b876e
AM
26013+
26014+ /* ro/rr branch */
1e00d052 26015+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
076b876e
AM
26016+
26017+ /* rw branch */
26018+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO},
1e00d052 26019+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
076b876e 26020+
1e00d052 26021+ {0, NULL}
1facf9fc 26022+};
26023+
1e00d052
AM
26024+static int br_attr_val(char *str, match_table_t table, substring_t args[])
26025+{
26026+ int attr, v;
26027+ char *p;
26028+
26029+ attr = 0;
26030+ do {
26031+ p = strchr(str, '+');
26032+ if (p)
26033+ *p = 0;
26034+ v = match_token(str, table, args);
076b876e
AM
26035+ if (v) {
26036+ if (v & AuBrAttr_CMOO_Mask)
26037+ attr &= ~AuBrAttr_CMOO_Mask;
1e00d052 26038+ attr |= v;
076b876e 26039+ } else {
1e00d052
AM
26040+ if (p)
26041+ *p = '+';
0c3ec466 26042+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
26043+ break;
26044+ }
26045+ if (p)
26046+ str = p + 1;
26047+ } while (p);
26048+
26049+ return attr;
26050+}
26051+
076b876e
AM
26052+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm)
26053+{
26054+ int sz;
26055+ const char *p;
26056+ char *q;
26057+
076b876e
AM
26058+ q = str->a;
26059+ *q = 0;
26060+ p = au_optstr(&perm, brattr);
26061+ if (p) {
26062+ sz = strlen(p);
26063+ memcpy(q, p, sz + 1);
26064+ q += sz;
26065+ } else
26066+ goto out;
26067+
26068+ do {
26069+ p = au_optstr(&perm, brattr);
26070+ if (p) {
26071+ *q++ = '+';
26072+ sz = strlen(p);
26073+ memcpy(q, p, sz + 1);
26074+ q += sz;
26075+ }
26076+ } while (p);
26077+
26078+out:
c1595e42 26079+ return q - str->a;
076b876e
AM
26080+}
26081+
4a4d8108 26082+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 26083+{
076b876e
AM
26084+ int val, bad, sz;
26085+ char *p;
1facf9fc 26086+ substring_t args[MAX_OPT_ARGS];
076b876e 26087+ au_br_perm_str_t attr;
1facf9fc 26088+
1e00d052
AM
26089+ p = strchr(perm, '+');
26090+ if (p)
26091+ *p = 0;
26092+ val = match_token(perm, brperm, args);
26093+ if (!val) {
26094+ if (p)
26095+ *p = '+';
0c3ec466 26096+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
26097+ val = AuBrPerm_RO;
26098+ goto out;
26099+ }
26100+ if (!p)
26101+ goto out;
26102+
076b876e
AM
26103+ val |= br_attr_val(p + 1, brattr, args);
26104+
26105+ bad = 0;
86dc4139 26106+ switch (val & AuBrPerm_Mask) {
1e00d052
AM
26107+ case AuBrPerm_RO:
26108+ case AuBrPerm_RR:
076b876e
AM
26109+ bad = val & AuBrWAttr_Mask;
26110+ val &= ~AuBrWAttr_Mask;
1e00d052
AM
26111+ break;
26112+ case AuBrPerm_RW:
076b876e
AM
26113+ bad = val & AuBrRAttr_Mask;
26114+ val &= ~AuBrRAttr_Mask;
1e00d052
AM
26115+ break;
26116+ }
c1595e42
JR
26117+
26118+ /*
26119+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs
26120+ * does not treat it as an error, just warning.
26121+ * this is a tiny guard for the user operation.
26122+ */
26123+ if (val & AuBrAttr_UNPIN) {
26124+ bad |= AuBrAttr_UNPIN;
26125+ val &= ~AuBrAttr_UNPIN;
26126+ }
26127+
076b876e
AM
26128+ if (unlikely(bad)) {
26129+ sz = au_do_optstr_br_attr(&attr, bad);
26130+ AuDebugOn(!sz);
26131+ pr_warn("ignored branch attribute %s\n", attr.a);
26132+ }
1e00d052
AM
26133+
26134+out:
1facf9fc 26135+ return val;
26136+}
26137+
076b876e 26138+void au_optstr_br_perm(au_br_perm_str_t *str, int perm)
1facf9fc 26139+{
076b876e
AM
26140+ au_br_perm_str_t attr;
26141+ const char *p;
26142+ char *q;
1e00d052
AM
26143+ int sz;
26144+
076b876e
AM
26145+ q = str->a;
26146+ p = au_optstr(&perm, brperm);
26147+ AuDebugOn(!p || !*p);
26148+ sz = strlen(p);
26149+ memcpy(q, p, sz + 1);
26150+ q += sz;
1e00d052 26151+
076b876e
AM
26152+ sz = au_do_optstr_br_attr(&attr, perm);
26153+ if (sz) {
26154+ *q++ = '+';
26155+ memcpy(q, attr.a, sz + 1);
1e00d052
AM
26156+ }
26157+
076b876e 26158+ AuDebugOn(strlen(str->a) >= sizeof(str->a));
1facf9fc 26159+}
26160+
26161+/* ---------------------------------------------------------------------- */
26162+
26163+static match_table_t udbalevel = {
26164+ {AuOpt_UDBA_REVAL, "reval"},
26165+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
26166+#ifdef CONFIG_AUFS_HNOTIFY
26167+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
26168+#ifdef CONFIG_AUFS_HFSNOTIFY
26169+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 26170+#endif
1facf9fc 26171+#endif
26172+ {-1, NULL}
26173+};
26174+
4a4d8108 26175+static int noinline_for_stack udba_val(char *str)
1facf9fc 26176+{
26177+ substring_t args[MAX_OPT_ARGS];
26178+
7f207e10 26179+ return match_token(str, udbalevel, args);
1facf9fc 26180+}
26181+
26182+const char *au_optstr_udba(int udba)
26183+{
076b876e 26184+ return au_parser_pattern(udba, udbalevel);
1facf9fc 26185+}
26186+
26187+/* ---------------------------------------------------------------------- */
26188+
26189+static match_table_t au_wbr_create_policy = {
26190+ {AuWbrCreate_TDP, "tdp"},
26191+ {AuWbrCreate_TDP, "top-down-parent"},
26192+ {AuWbrCreate_RR, "rr"},
26193+ {AuWbrCreate_RR, "round-robin"},
26194+ {AuWbrCreate_MFS, "mfs"},
26195+ {AuWbrCreate_MFS, "most-free-space"},
26196+ {AuWbrCreate_MFSV, "mfs:%d"},
26197+ {AuWbrCreate_MFSV, "most-free-space:%d"},
26198+
f2c43d5f
AM
26199+ /* top-down regardless the parent, and then mfs */
26200+ {AuWbrCreate_TDMFS, "tdmfs:%d"},
26201+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"},
26202+
1facf9fc 26203+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
26204+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
26205+ {AuWbrCreate_PMFS, "pmfs"},
26206+ {AuWbrCreate_PMFSV, "pmfs:%d"},
392086de
AM
26207+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"},
26208+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"},
1facf9fc 26209+
26210+ {-1, NULL}
26211+};
26212+
1facf9fc 26213+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
26214+ struct au_opt_wbr_create *create)
26215+{
26216+ int err;
26217+ unsigned long long ull;
26218+
26219+ err = 0;
a2654f78 26220+ if (!match_u64(arg, &ull))
1facf9fc 26221+ create->mfsrr_watermark = ull;
26222+ else {
4a4d8108 26223+ pr_err("bad integer in %s\n", str);
1facf9fc 26224+ err = -EINVAL;
26225+ }
26226+
26227+ return err;
26228+}
26229+
26230+static int au_wbr_mfs_sec(substring_t *arg, char *str,
26231+ struct au_opt_wbr_create *create)
26232+{
26233+ int n, err;
26234+
26235+ err = 0;
027c5e7a 26236+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 26237+ create->mfs_second = n;
26238+ else {
4a4d8108 26239+ pr_err("bad integer in %s\n", str);
1facf9fc 26240+ err = -EINVAL;
26241+ }
26242+
26243+ return err;
26244+}
26245+
4a4d8108
AM
26246+static int noinline_for_stack
26247+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 26248+{
26249+ int err, e;
26250+ substring_t args[MAX_OPT_ARGS];
26251+
26252+ err = match_token(str, au_wbr_create_policy, args);
26253+ create->wbr_create = err;
26254+ switch (err) {
26255+ case AuWbrCreate_MFSRRV:
f2c43d5f 26256+ case AuWbrCreate_TDMFSV:
392086de 26257+ case AuWbrCreate_PMFSRRV:
1facf9fc 26258+ e = au_wbr_mfs_wmark(&args[0], str, create);
26259+ if (!e)
26260+ e = au_wbr_mfs_sec(&args[1], str, create);
26261+ if (unlikely(e))
26262+ err = e;
26263+ break;
26264+ case AuWbrCreate_MFSRR:
f2c43d5f 26265+ case AuWbrCreate_TDMFS:
392086de 26266+ case AuWbrCreate_PMFSRR:
1facf9fc 26267+ e = au_wbr_mfs_wmark(&args[0], str, create);
26268+ if (unlikely(e)) {
26269+ err = e;
26270+ break;
26271+ }
26272+ /*FALLTHROUGH*/
26273+ case AuWbrCreate_MFS:
26274+ case AuWbrCreate_PMFS:
027c5e7a 26275+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 26276+ break;
26277+ case AuWbrCreate_MFSV:
26278+ case AuWbrCreate_PMFSV:
26279+ e = au_wbr_mfs_sec(&args[0], str, create);
26280+ if (unlikely(e))
26281+ err = e;
26282+ break;
26283+ }
26284+
26285+ return err;
26286+}
26287+
26288+const char *au_optstr_wbr_create(int wbr_create)
26289+{
076b876e 26290+ return au_parser_pattern(wbr_create, au_wbr_create_policy);
1facf9fc 26291+}
26292+
26293+static match_table_t au_wbr_copyup_policy = {
26294+ {AuWbrCopyup_TDP, "tdp"},
26295+ {AuWbrCopyup_TDP, "top-down-parent"},
26296+ {AuWbrCopyup_BUP, "bup"},
26297+ {AuWbrCopyup_BUP, "bottom-up-parent"},
26298+ {AuWbrCopyup_BU, "bu"},
26299+ {AuWbrCopyup_BU, "bottom-up"},
26300+ {-1, NULL}
26301+};
26302+
4a4d8108 26303+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 26304+{
26305+ substring_t args[MAX_OPT_ARGS];
26306+
26307+ return match_token(str, au_wbr_copyup_policy, args);
26308+}
26309+
26310+const char *au_optstr_wbr_copyup(int wbr_copyup)
26311+{
076b876e 26312+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy);
1facf9fc 26313+}
26314+
26315+/* ---------------------------------------------------------------------- */
26316+
26317+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
26318+
26319+static void dump_opts(struct au_opts *opts)
26320+{
26321+#ifdef CONFIG_AUFS_DEBUG
26322+ /* reduce stack space */
26323+ union {
26324+ struct au_opt_add *add;
26325+ struct au_opt_del *del;
26326+ struct au_opt_mod *mod;
26327+ struct au_opt_xino *xino;
26328+ struct au_opt_xino_itrunc *xino_itrunc;
26329+ struct au_opt_wbr_create *create;
26330+ } u;
26331+ struct au_opt *opt;
26332+
26333+ opt = opts->opt;
26334+ while (opt->type != Opt_tail) {
26335+ switch (opt->type) {
26336+ case Opt_add:
26337+ u.add = &opt->add;
26338+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
26339+ u.add->bindex, u.add->pathname, u.add->perm,
26340+ u.add->path.dentry);
26341+ break;
26342+ case Opt_del:
26343+ case Opt_idel:
26344+ u.del = &opt->del;
26345+ AuDbg("del {%s, %p}\n",
26346+ u.del->pathname, u.del->h_path.dentry);
26347+ break;
26348+ case Opt_mod:
26349+ case Opt_imod:
26350+ u.mod = &opt->mod;
26351+ AuDbg("mod {%s, 0x%x, %p}\n",
26352+ u.mod->path, u.mod->perm, u.mod->h_root);
26353+ break;
26354+ case Opt_append:
26355+ u.add = &opt->add;
26356+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
26357+ u.add->bindex, u.add->pathname, u.add->perm,
26358+ u.add->path.dentry);
26359+ break;
26360+ case Opt_prepend:
26361+ u.add = &opt->add;
26362+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
26363+ u.add->bindex, u.add->pathname, u.add->perm,
26364+ u.add->path.dentry);
26365+ break;
26366+ case Opt_dirwh:
26367+ AuDbg("dirwh %d\n", opt->dirwh);
26368+ break;
26369+ case Opt_rdcache:
26370+ AuDbg("rdcache %d\n", opt->rdcache);
26371+ break;
26372+ case Opt_rdblk:
26373+ AuDbg("rdblk %u\n", opt->rdblk);
26374+ break;
dece6358
AM
26375+ case Opt_rdblk_def:
26376+ AuDbg("rdblk_def\n");
26377+ break;
1facf9fc 26378+ case Opt_rdhash:
26379+ AuDbg("rdhash %u\n", opt->rdhash);
26380+ break;
dece6358
AM
26381+ case Opt_rdhash_def:
26382+ AuDbg("rdhash_def\n");
26383+ break;
1facf9fc 26384+ case Opt_xino:
26385+ u.xino = &opt->xino;
523b37e3 26386+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
1facf9fc 26387+ break;
26388+ case Opt_trunc_xino:
26389+ AuLabel(trunc_xino);
26390+ break;
26391+ case Opt_notrunc_xino:
26392+ AuLabel(notrunc_xino);
26393+ break;
26394+ case Opt_trunc_xino_path:
26395+ case Opt_itrunc_xino:
26396+ u.xino_itrunc = &opt->xino_itrunc;
26397+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
26398+ break;
1facf9fc 26399+ case Opt_noxino:
26400+ AuLabel(noxino);
26401+ break;
26402+ case Opt_trunc_xib:
26403+ AuLabel(trunc_xib);
26404+ break;
26405+ case Opt_notrunc_xib:
26406+ AuLabel(notrunc_xib);
26407+ break;
dece6358
AM
26408+ case Opt_shwh:
26409+ AuLabel(shwh);
26410+ break;
26411+ case Opt_noshwh:
26412+ AuLabel(noshwh);
26413+ break;
076b876e
AM
26414+ case Opt_dirperm1:
26415+ AuLabel(dirperm1);
26416+ break;
26417+ case Opt_nodirperm1:
26418+ AuLabel(nodirperm1);
26419+ break;
1facf9fc 26420+ case Opt_plink:
26421+ AuLabel(plink);
26422+ break;
26423+ case Opt_noplink:
26424+ AuLabel(noplink);
26425+ break;
26426+ case Opt_list_plink:
26427+ AuLabel(list_plink);
26428+ break;
26429+ case Opt_udba:
26430+ AuDbg("udba %d, %s\n",
26431+ opt->udba, au_optstr_udba(opt->udba));
26432+ break;
4a4d8108
AM
26433+ case Opt_dio:
26434+ AuLabel(dio);
26435+ break;
26436+ case Opt_nodio:
26437+ AuLabel(nodio);
26438+ break;
1facf9fc 26439+ case Opt_diropq_a:
26440+ AuLabel(diropq_a);
26441+ break;
26442+ case Opt_diropq_w:
26443+ AuLabel(diropq_w);
26444+ break;
26445+ case Opt_warn_perm:
26446+ AuLabel(warn_perm);
26447+ break;
26448+ case Opt_nowarn_perm:
26449+ AuLabel(nowarn_perm);
26450+ break;
1facf9fc 26451+ case Opt_verbose:
26452+ AuLabel(verbose);
26453+ break;
26454+ case Opt_noverbose:
26455+ AuLabel(noverbose);
26456+ break;
26457+ case Opt_sum:
26458+ AuLabel(sum);
26459+ break;
26460+ case Opt_nosum:
26461+ AuLabel(nosum);
26462+ break;
26463+ case Opt_wsum:
26464+ AuLabel(wsum);
26465+ break;
26466+ case Opt_wbr_create:
26467+ u.create = &opt->wbr_create;
26468+ AuDbg("create %d, %s\n", u.create->wbr_create,
26469+ au_optstr_wbr_create(u.create->wbr_create));
26470+ switch (u.create->wbr_create) {
26471+ case AuWbrCreate_MFSV:
26472+ case AuWbrCreate_PMFSV:
26473+ AuDbg("%d sec\n", u.create->mfs_second);
26474+ break;
26475+ case AuWbrCreate_MFSRR:
f2c43d5f 26476+ case AuWbrCreate_TDMFS:
1facf9fc 26477+ AuDbg("%llu watermark\n",
26478+ u.create->mfsrr_watermark);
26479+ break;
26480+ case AuWbrCreate_MFSRRV:
f2c43d5f 26481+ case AuWbrCreate_TDMFSV:
392086de 26482+ case AuWbrCreate_PMFSRRV:
1facf9fc 26483+ AuDbg("%llu watermark, %d sec\n",
26484+ u.create->mfsrr_watermark,
26485+ u.create->mfs_second);
26486+ break;
26487+ }
26488+ break;
26489+ case Opt_wbr_copyup:
26490+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
26491+ au_optstr_wbr_copyup(opt->wbr_copyup));
26492+ break;
076b876e
AM
26493+ case Opt_fhsm_sec:
26494+ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
26495+ break;
8b6a4947
AM
26496+ case Opt_dirren:
26497+ AuLabel(dirren);
26498+ break;
26499+ case Opt_nodirren:
26500+ AuLabel(nodirren);
26501+ break;
c1595e42
JR
26502+ case Opt_acl:
26503+ AuLabel(acl);
26504+ break;
26505+ case Opt_noacl:
26506+ AuLabel(noacl);
26507+ break;
1facf9fc 26508+ default:
26509+ BUG();
26510+ }
26511+ opt++;
26512+ }
26513+#endif
26514+}
26515+
26516+void au_opts_free(struct au_opts *opts)
26517+{
26518+ struct au_opt *opt;
26519+
26520+ opt = opts->opt;
26521+ while (opt->type != Opt_tail) {
26522+ switch (opt->type) {
26523+ case Opt_add:
26524+ case Opt_append:
26525+ case Opt_prepend:
26526+ path_put(&opt->add.path);
26527+ break;
26528+ case Opt_del:
26529+ case Opt_idel:
26530+ path_put(&opt->del.h_path);
26531+ break;
26532+ case Opt_mod:
26533+ case Opt_imod:
26534+ dput(opt->mod.h_root);
26535+ break;
26536+ case Opt_xino:
26537+ fput(opt->xino.file);
26538+ break;
26539+ }
26540+ opt++;
26541+ }
26542+}
26543+
26544+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
26545+ aufs_bindex_t bindex)
26546+{
26547+ int err;
26548+ struct au_opt_add *add = &opt->add;
26549+ char *p;
26550+
26551+ add->bindex = bindex;
1e00d052 26552+ add->perm = AuBrPerm_RO;
1facf9fc 26553+ add->pathname = opt_str;
26554+ p = strchr(opt_str, '=');
26555+ if (p) {
26556+ *p++ = 0;
26557+ if (*p)
26558+ add->perm = br_perm_val(p);
26559+ }
26560+
26561+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
26562+ if (!err) {
26563+ if (!p) {
26564+ add->perm = AuBrPerm_RO;
26565+ if (au_test_fs_rr(add->path.dentry->d_sb))
26566+ add->perm = AuBrPerm_RR;
2121bcd9 26567+ else if (!bindex && !(sb_flags & SB_RDONLY))
1facf9fc 26568+ add->perm = AuBrPerm_RW;
26569+ }
26570+ opt->type = Opt_add;
26571+ goto out;
26572+ }
4a4d8108 26573+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 26574+ err = -EINVAL;
26575+
4f0767ce 26576+out:
1facf9fc 26577+ return err;
26578+}
26579+
26580+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
26581+{
26582+ int err;
26583+
26584+ del->pathname = args[0].from;
26585+ AuDbg("del path %s\n", del->pathname);
26586+
26587+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
26588+ if (unlikely(err))
4a4d8108 26589+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 26590+
26591+ return err;
26592+}
26593+
26594+#if 0 /* reserved for future use */
26595+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
26596+ struct au_opt_del *del, substring_t args[])
26597+{
26598+ int err;
26599+ struct dentry *root;
26600+
26601+ err = -EINVAL;
26602+ root = sb->s_root;
26603+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26604+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26605+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26606+ goto out;
26607+ }
26608+
26609+ err = 0;
26610+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
26611+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
26612+
4f0767ce 26613+out:
1facf9fc 26614+ aufs_read_unlock(root, !AuLock_IR);
26615+ return err;
26616+}
26617+#endif
26618+
4a4d8108
AM
26619+static int noinline_for_stack
26620+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 26621+{
26622+ int err;
26623+ struct path path;
26624+ char *p;
26625+
26626+ err = -EINVAL;
26627+ mod->path = args[0].from;
26628+ p = strchr(mod->path, '=');
26629+ if (unlikely(!p)) {
acd2b654 26630+ pr_err("no permission %s\n", args[0].from);
1facf9fc 26631+ goto out;
26632+ }
26633+
26634+ *p++ = 0;
26635+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
26636+ if (unlikely(err)) {
4a4d8108 26637+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 26638+ goto out;
26639+ }
26640+
26641+ mod->perm = br_perm_val(p);
26642+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
26643+ mod->h_root = dget(path.dentry);
26644+ path_put(&path);
26645+
4f0767ce 26646+out:
1facf9fc 26647+ return err;
26648+}
26649+
26650+#if 0 /* reserved for future use */
26651+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
26652+ struct au_opt_mod *mod, substring_t args[])
26653+{
26654+ int err;
26655+ struct dentry *root;
26656+
26657+ err = -EINVAL;
26658+ root = sb->s_root;
26659+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26660+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26661+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26662+ goto out;
26663+ }
26664+
26665+ err = 0;
26666+ mod->perm = br_perm_val(args[1].from);
26667+ AuDbg("mod path %s, perm 0x%x, %s\n",
26668+ mod->path, mod->perm, args[1].from);
26669+ mod->h_root = dget(au_h_dptr(root, bindex));
26670+
4f0767ce 26671+out:
1facf9fc 26672+ aufs_read_unlock(root, !AuLock_IR);
26673+ return err;
26674+}
26675+#endif
26676+
26677+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
26678+ substring_t args[])
26679+{
26680+ int err;
26681+ struct file *file;
26682+
83b672a5 26683+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0);
1facf9fc 26684+ err = PTR_ERR(file);
26685+ if (IS_ERR(file))
26686+ goto out;
26687+
26688+ err = -EINVAL;
2000de60 26689+ if (unlikely(file->f_path.dentry->d_sb == sb)) {
1facf9fc 26690+ fput(file);
4a4d8108 26691+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 26692+ goto out;
26693+ }
26694+
26695+ err = 0;
26696+ xino->file = file;
26697+ xino->path = args[0].from;
26698+
4f0767ce 26699+out:
1facf9fc 26700+ return err;
26701+}
26702+
4a4d8108
AM
26703+static int noinline_for_stack
26704+au_opts_parse_xino_itrunc_path(struct super_block *sb,
26705+ struct au_opt_xino_itrunc *xino_itrunc,
26706+ substring_t args[])
1facf9fc 26707+{
26708+ int err;
5afbbe0d 26709+ aufs_bindex_t bbot, bindex;
1facf9fc 26710+ struct path path;
26711+ struct dentry *root;
26712+
26713+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
26714+ if (unlikely(err)) {
4a4d8108 26715+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 26716+ goto out;
26717+ }
26718+
26719+ xino_itrunc->bindex = -1;
26720+ root = sb->s_root;
26721+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d
AM
26722+ bbot = au_sbbot(sb);
26723+ for (bindex = 0; bindex <= bbot; bindex++) {
1facf9fc 26724+ if (au_h_dptr(root, bindex) == path.dentry) {
26725+ xino_itrunc->bindex = bindex;
26726+ break;
26727+ }
26728+ }
26729+ aufs_read_unlock(root, !AuLock_IR);
26730+ path_put(&path);
26731+
26732+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 26733+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 26734+ err = -EINVAL;
26735+ }
26736+
4f0767ce 26737+out:
1facf9fc 26738+ return err;
26739+}
26740+
26741+/* called without aufs lock */
26742+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
26743+{
26744+ int err, n, token;
26745+ aufs_bindex_t bindex;
26746+ unsigned char skipped;
26747+ struct dentry *root;
26748+ struct au_opt *opt, *opt_tail;
26749+ char *opt_str;
26750+ /* reduce the stack space */
26751+ union {
26752+ struct au_opt_xino_itrunc *xino_itrunc;
26753+ struct au_opt_wbr_create *create;
26754+ } u;
26755+ struct {
26756+ substring_t args[MAX_OPT_ARGS];
26757+ } *a;
26758+
26759+ err = -ENOMEM;
26760+ a = kmalloc(sizeof(*a), GFP_NOFS);
26761+ if (unlikely(!a))
26762+ goto out;
26763+
26764+ root = sb->s_root;
26765+ err = 0;
26766+ bindex = 0;
26767+ opt = opts->opt;
26768+ opt_tail = opt + opts->max_opt - 1;
26769+ opt->type = Opt_tail;
26770+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
26771+ err = -EINVAL;
26772+ skipped = 0;
26773+ token = match_token(opt_str, options, a->args);
26774+ switch (token) {
26775+ case Opt_br:
26776+ err = 0;
26777+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
26778+ && *opt_str) {
26779+ err = opt_add(opt, opt_str, opts->sb_flags,
26780+ bindex++);
26781+ if (unlikely(!err && ++opt > opt_tail)) {
26782+ err = -E2BIG;
26783+ break;
26784+ }
26785+ opt->type = Opt_tail;
26786+ skipped = 1;
26787+ }
26788+ break;
26789+ case Opt_add:
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+ bindex = n;
26795+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
26796+ bindex);
26797+ if (!err)
26798+ opt->type = token;
26799+ break;
26800+ case Opt_append:
26801+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26802+ /*dummy bindex*/1);
26803+ if (!err)
26804+ opt->type = token;
26805+ break;
26806+ case Opt_prepend:
26807+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26808+ /*bindex*/0);
26809+ if (!err)
26810+ opt->type = token;
26811+ break;
26812+ case Opt_del:
26813+ err = au_opts_parse_del(&opt->del, a->args);
26814+ if (!err)
26815+ opt->type = token;
26816+ break;
26817+#if 0 /* reserved for future use */
26818+ case Opt_idel:
26819+ del->pathname = "(indexed)";
26820+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 26821+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26822+ break;
26823+ }
26824+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
26825+ if (!err)
26826+ opt->type = token;
26827+ break;
26828+#endif
26829+ case Opt_mod:
26830+ err = au_opts_parse_mod(&opt->mod, a->args);
26831+ if (!err)
26832+ opt->type = token;
26833+ break;
26834+#ifdef IMOD /* reserved for future use */
26835+ case Opt_imod:
26836+ u.mod->path = "(indexed)";
26837+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26838+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26839+ break;
26840+ }
26841+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
26842+ if (!err)
26843+ opt->type = token;
26844+ break;
26845+#endif
26846+ case Opt_xino:
26847+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
26848+ if (!err)
26849+ opt->type = token;
26850+ break;
26851+
26852+ case Opt_trunc_xino_path:
26853+ err = au_opts_parse_xino_itrunc_path
26854+ (sb, &opt->xino_itrunc, a->args);
26855+ if (!err)
26856+ opt->type = token;
26857+ break;
26858+
26859+ case Opt_itrunc_xino:
26860+ u.xino_itrunc = &opt->xino_itrunc;
26861+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26862+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26863+ break;
26864+ }
26865+ u.xino_itrunc->bindex = n;
26866+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26867+ if (n < 0 || au_sbbot(sb) < n) {
4a4d8108 26868+ pr_err("out of bounds, %d\n", n);
1facf9fc 26869+ aufs_read_unlock(root, !AuLock_IR);
26870+ break;
26871+ }
26872+ aufs_read_unlock(root, !AuLock_IR);
26873+ err = 0;
26874+ opt->type = token;
26875+ break;
26876+
26877+ case Opt_dirwh:
26878+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
26879+ break;
26880+ err = 0;
26881+ opt->type = token;
26882+ break;
26883+
26884+ case Opt_rdcache:
027c5e7a
AM
26885+ if (unlikely(match_int(&a->args[0], &n))) {
26886+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26887+ break;
027c5e7a
AM
26888+ }
26889+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
26890+ pr_err("rdcache must be smaller than %d\n",
26891+ AUFS_RDCACHE_MAX);
26892+ break;
26893+ }
26894+ opt->rdcache = n;
1facf9fc 26895+ err = 0;
26896+ opt->type = token;
26897+ break;
26898+ case Opt_rdblk:
26899+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26900+ || n < 0
1facf9fc 26901+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 26902+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26903+ break;
26904+ }
1308ab2a 26905+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
26906+ pr_err("rdblk must be larger than %d\n",
26907+ NAME_MAX);
1facf9fc 26908+ break;
26909+ }
26910+ opt->rdblk = n;
26911+ err = 0;
26912+ opt->type = token;
26913+ break;
26914+ case Opt_rdhash:
26915+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26916+ || n < 0
1facf9fc 26917+ || n * sizeof(struct hlist_head)
26918+ > KMALLOC_MAX_SIZE)) {
4a4d8108 26919+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26920+ break;
26921+ }
26922+ opt->rdhash = n;
26923+ err = 0;
26924+ opt->type = token;
26925+ break;
26926+
26927+ case Opt_trunc_xino:
26928+ case Opt_notrunc_xino:
26929+ case Opt_noxino:
26930+ case Opt_trunc_xib:
26931+ case Opt_notrunc_xib:
dece6358
AM
26932+ case Opt_shwh:
26933+ case Opt_noshwh:
076b876e
AM
26934+ case Opt_dirperm1:
26935+ case Opt_nodirperm1:
1facf9fc 26936+ case Opt_plink:
26937+ case Opt_noplink:
26938+ case Opt_list_plink:
4a4d8108
AM
26939+ case Opt_dio:
26940+ case Opt_nodio:
1facf9fc 26941+ case Opt_diropq_a:
26942+ case Opt_diropq_w:
26943+ case Opt_warn_perm:
26944+ case Opt_nowarn_perm:
1facf9fc 26945+ case Opt_verbose:
26946+ case Opt_noverbose:
26947+ case Opt_sum:
26948+ case Opt_nosum:
26949+ case Opt_wsum:
dece6358
AM
26950+ case Opt_rdblk_def:
26951+ case Opt_rdhash_def:
8b6a4947
AM
26952+ case Opt_dirren:
26953+ case Opt_nodirren:
c1595e42
JR
26954+ case Opt_acl:
26955+ case Opt_noacl:
1facf9fc 26956+ err = 0;
26957+ opt->type = token;
26958+ break;
26959+
26960+ case Opt_udba:
26961+ opt->udba = udba_val(a->args[0].from);
26962+ if (opt->udba >= 0) {
26963+ err = 0;
26964+ opt->type = token;
26965+ } else
4a4d8108 26966+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26967+ break;
26968+
26969+ case Opt_wbr_create:
26970+ u.create = &opt->wbr_create;
26971+ u.create->wbr_create
26972+ = au_wbr_create_val(a->args[0].from, u.create);
26973+ if (u.create->wbr_create >= 0) {
26974+ err = 0;
26975+ opt->type = token;
26976+ } else
4a4d8108 26977+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26978+ break;
26979+ case Opt_wbr_copyup:
26980+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
26981+ if (opt->wbr_copyup >= 0) {
26982+ err = 0;
26983+ opt->type = token;
26984+ } else
4a4d8108 26985+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26986+ break;
26987+
076b876e
AM
26988+ case Opt_fhsm_sec:
26989+ if (unlikely(match_int(&a->args[0], &n)
26990+ || n < 0)) {
26991+ pr_err("bad integer in %s\n", opt_str);
26992+ break;
26993+ }
26994+ if (sysaufs_brs) {
26995+ opt->fhsm_second = n;
26996+ opt->type = token;
26997+ } else
26998+ pr_warn("ignored %s\n", opt_str);
26999+ err = 0;
27000+ break;
27001+
1facf9fc 27002+ case Opt_ignore:
0c3ec466 27003+ pr_warn("ignored %s\n", opt_str);
1facf9fc 27004+ /*FALLTHROUGH*/
27005+ case Opt_ignore_silent:
27006+ skipped = 1;
27007+ err = 0;
27008+ break;
27009+ case Opt_err:
4a4d8108 27010+ pr_err("unknown option %s\n", opt_str);
1facf9fc 27011+ break;
27012+ }
27013+
27014+ if (!err && !skipped) {
27015+ if (unlikely(++opt > opt_tail)) {
27016+ err = -E2BIG;
27017+ opt--;
27018+ opt->type = Opt_tail;
27019+ break;
27020+ }
27021+ opt->type = Opt_tail;
27022+ }
27023+ }
27024+
9f237c51 27025+ au_kfree_rcu(a);
1facf9fc 27026+ dump_opts(opts);
27027+ if (unlikely(err))
27028+ au_opts_free(opts);
27029+
4f0767ce 27030+out:
1facf9fc 27031+ return err;
27032+}
27033+
27034+static int au_opt_wbr_create(struct super_block *sb,
27035+ struct au_opt_wbr_create *create)
27036+{
27037+ int err;
27038+ struct au_sbinfo *sbinfo;
27039+
dece6358
AM
27040+ SiMustWriteLock(sb);
27041+
1facf9fc 27042+ err = 1; /* handled */
27043+ sbinfo = au_sbi(sb);
27044+ if (sbinfo->si_wbr_create_ops->fin) {
27045+ err = sbinfo->si_wbr_create_ops->fin(sb);
27046+ if (!err)
27047+ err = 1;
27048+ }
27049+
27050+ sbinfo->si_wbr_create = create->wbr_create;
27051+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
27052+ switch (create->wbr_create) {
27053+ case AuWbrCreate_MFSRRV:
27054+ case AuWbrCreate_MFSRR:
f2c43d5f
AM
27055+ case AuWbrCreate_TDMFS:
27056+ case AuWbrCreate_TDMFSV:
392086de
AM
27057+ case AuWbrCreate_PMFSRR:
27058+ case AuWbrCreate_PMFSRRV:
1facf9fc 27059+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
27060+ /*FALLTHROUGH*/
27061+ case AuWbrCreate_MFS:
27062+ case AuWbrCreate_MFSV:
27063+ case AuWbrCreate_PMFS:
27064+ case AuWbrCreate_PMFSV:
e49829fe
JR
27065+ sbinfo->si_wbr_mfs.mfs_expire
27066+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 27067+ break;
27068+ }
27069+
27070+ if (sbinfo->si_wbr_create_ops->init)
27071+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
27072+
27073+ return err;
27074+}
27075+
27076+/*
27077+ * returns,
27078+ * plus: processed without an error
27079+ * zero: unprocessed
27080+ */
27081+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
27082+ struct au_opts *opts)
27083+{
27084+ int err;
27085+ struct au_sbinfo *sbinfo;
27086+
dece6358
AM
27087+ SiMustWriteLock(sb);
27088+
1facf9fc 27089+ err = 1; /* handled */
27090+ sbinfo = au_sbi(sb);
27091+ switch (opt->type) {
27092+ case Opt_udba:
27093+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
27094+ sbinfo->si_mntflags |= opt->udba;
27095+ opts->given_udba |= opt->udba;
27096+ break;
27097+
27098+ case Opt_plink:
27099+ au_opt_set(sbinfo->si_mntflags, PLINK);
27100+ break;
27101+ case Opt_noplink:
27102+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 27103+ au_plink_put(sb, /*verbose*/1);
1facf9fc 27104+ au_opt_clr(sbinfo->si_mntflags, PLINK);
27105+ break;
27106+ case Opt_list_plink:
27107+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
27108+ au_plink_list(sb);
27109+ break;
27110+
4a4d8108
AM
27111+ case Opt_dio:
27112+ au_opt_set(sbinfo->si_mntflags, DIO);
27113+ au_fset_opts(opts->flags, REFRESH_DYAOP);
27114+ break;
27115+ case Opt_nodio:
27116+ au_opt_clr(sbinfo->si_mntflags, DIO);
27117+ au_fset_opts(opts->flags, REFRESH_DYAOP);
27118+ break;
27119+
076b876e
AM
27120+ case Opt_fhsm_sec:
27121+ au_fhsm_set(sbinfo, opt->fhsm_second);
27122+ break;
27123+
1facf9fc 27124+ case Opt_diropq_a:
27125+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
27126+ break;
27127+ case Opt_diropq_w:
27128+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
27129+ break;
27130+
27131+ case Opt_warn_perm:
27132+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
27133+ break;
27134+ case Opt_nowarn_perm:
27135+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
27136+ break;
27137+
1facf9fc 27138+ case Opt_verbose:
27139+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
27140+ break;
27141+ case Opt_noverbose:
27142+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
27143+ break;
27144+
27145+ case Opt_sum:
27146+ au_opt_set(sbinfo->si_mntflags, SUM);
27147+ break;
27148+ case Opt_wsum:
27149+ au_opt_clr(sbinfo->si_mntflags, SUM);
27150+ au_opt_set(sbinfo->si_mntflags, SUM_W);
eca34b5c 27151+ break;
1facf9fc 27152+ case Opt_nosum:
27153+ au_opt_clr(sbinfo->si_mntflags, SUM);
27154+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
27155+ break;
27156+
27157+ case Opt_wbr_create:
27158+ err = au_opt_wbr_create(sb, &opt->wbr_create);
27159+ break;
27160+ case Opt_wbr_copyup:
27161+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
27162+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
27163+ break;
27164+
27165+ case Opt_dirwh:
27166+ sbinfo->si_dirwh = opt->dirwh;
27167+ break;
27168+
27169+ case Opt_rdcache:
e49829fe
JR
27170+ sbinfo->si_rdcache
27171+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 27172+ break;
27173+ case Opt_rdblk:
27174+ sbinfo->si_rdblk = opt->rdblk;
27175+ break;
dece6358
AM
27176+ case Opt_rdblk_def:
27177+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
27178+ break;
1facf9fc 27179+ case Opt_rdhash:
27180+ sbinfo->si_rdhash = opt->rdhash;
27181+ break;
dece6358
AM
27182+ case Opt_rdhash_def:
27183+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
27184+ break;
27185+
27186+ case Opt_shwh:
27187+ au_opt_set(sbinfo->si_mntflags, SHWH);
27188+ break;
27189+ case Opt_noshwh:
27190+ au_opt_clr(sbinfo->si_mntflags, SHWH);
27191+ break;
1facf9fc 27192+
076b876e
AM
27193+ case Opt_dirperm1:
27194+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
27195+ break;
27196+ case Opt_nodirperm1:
27197+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
27198+ break;
27199+
1facf9fc 27200+ case Opt_trunc_xino:
27201+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
27202+ break;
27203+ case Opt_notrunc_xino:
27204+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
27205+ break;
27206+
27207+ case Opt_trunc_xino_path:
27208+ case Opt_itrunc_xino:
acd2b654
AM
27209+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex,
27210+ /*idx_begin*/0);
1facf9fc 27211+ if (!err)
27212+ err = 1;
27213+ break;
27214+
27215+ case Opt_trunc_xib:
27216+ au_fset_opts(opts->flags, TRUNC_XIB);
27217+ break;
27218+ case Opt_notrunc_xib:
27219+ au_fclr_opts(opts->flags, TRUNC_XIB);
27220+ break;
27221+
8b6a4947
AM
27222+ case Opt_dirren:
27223+ err = 1;
27224+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27225+ err = au_dr_opt_set(sb);
27226+ if (!err)
27227+ err = 1;
27228+ }
27229+ if (err == 1)
27230+ au_opt_set(sbinfo->si_mntflags, DIRREN);
27231+ break;
27232+ case Opt_nodirren:
27233+ err = 1;
27234+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27235+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags,
27236+ DR_FLUSHED));
27237+ if (!err)
27238+ err = 1;
27239+ }
27240+ if (err == 1)
27241+ au_opt_clr(sbinfo->si_mntflags, DIRREN);
27242+ break;
27243+
c1595e42 27244+ case Opt_acl:
2121bcd9 27245+ sb->s_flags |= SB_POSIXACL;
c1595e42
JR
27246+ break;
27247+ case Opt_noacl:
2121bcd9 27248+ sb->s_flags &= ~SB_POSIXACL;
c1595e42
JR
27249+ break;
27250+
1facf9fc 27251+ default:
27252+ err = 0;
27253+ break;
27254+ }
27255+
27256+ return err;
27257+}
27258+
27259+/*
27260+ * returns tri-state.
27261+ * plus: processed without an error
27262+ * zero: unprocessed
27263+ * minus: error
27264+ */
27265+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
27266+ struct au_opts *opts)
27267+{
27268+ int err, do_refresh;
27269+
27270+ err = 0;
27271+ switch (opt->type) {
27272+ case Opt_append:
5afbbe0d 27273+ opt->add.bindex = au_sbbot(sb) + 1;
1facf9fc 27274+ if (opt->add.bindex < 0)
27275+ opt->add.bindex = 0;
27276+ goto add;
eca34b5c 27277+ /* Always goto add, not fallthrough */
1facf9fc 27278+ case Opt_prepend:
27279+ opt->add.bindex = 0;
eca34b5c 27280+ /* fallthrough */
f6b6e03d 27281+ add: /* indented label */
1facf9fc 27282+ case Opt_add:
27283+ err = au_br_add(sb, &opt->add,
27284+ au_ftest_opts(opts->flags, REMOUNT));
27285+ if (!err) {
27286+ err = 1;
027c5e7a 27287+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27288+ }
27289+ break;
27290+
27291+ case Opt_del:
27292+ case Opt_idel:
27293+ err = au_br_del(sb, &opt->del,
27294+ au_ftest_opts(opts->flags, REMOUNT));
27295+ if (!err) {
27296+ err = 1;
27297+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 27298+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27299+ }
27300+ break;
27301+
27302+ case Opt_mod:
27303+ case Opt_imod:
27304+ err = au_br_mod(sb, &opt->mod,
27305+ au_ftest_opts(opts->flags, REMOUNT),
27306+ &do_refresh);
27307+ if (!err) {
27308+ err = 1;
027c5e7a
AM
27309+ if (do_refresh)
27310+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27311+ }
27312+ break;
27313+ }
1facf9fc 27314+ return err;
27315+}
27316+
27317+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
27318+ struct au_opt_xino **opt_xino,
27319+ struct au_opts *opts)
27320+{
27321+ int err;
1facf9fc 27322+
27323+ err = 0;
27324+ switch (opt->type) {
27325+ case Opt_xino:
062440b3
AM
27326+ err = au_xino_set(sb, &opt->xino,
27327+ !!au_ftest_opts(opts->flags, REMOUNT));
27328+ if (unlikely(err))
27329+ break;
27330+
27331+ *opt_xino = &opt->xino;
1facf9fc 27332+ break;
27333+
27334+ case Opt_noxino:
27335+ au_xino_clr(sb);
1facf9fc 27336+ *opt_xino = (void *)-1;
27337+ break;
27338+ }
27339+
27340+ return err;
27341+}
27342+
27343+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27344+ unsigned int pending)
27345+{
076b876e 27346+ int err, fhsm;
5afbbe0d 27347+ aufs_bindex_t bindex, bbot;
79b8bda9 27348+ unsigned char do_plink, skip, do_free, can_no_dreval;
1facf9fc 27349+ struct au_branch *br;
27350+ struct au_wbr *wbr;
79b8bda9 27351+ struct dentry *root, *dentry;
1facf9fc 27352+ struct inode *dir, *h_dir;
27353+ struct au_sbinfo *sbinfo;
27354+ struct au_hinode *hdir;
27355+
dece6358
AM
27356+ SiMustAnyLock(sb);
27357+
1facf9fc 27358+ sbinfo = au_sbi(sb);
27359+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
27360+
2121bcd9 27361+ if (!(sb_flags & SB_RDONLY)) {
dece6358 27362+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 27363+ pr_warn("first branch should be rw\n");
dece6358 27364+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
febd17d6 27365+ pr_warn_once("shwh should be used with ro\n");
dece6358 27366+ }
1facf9fc 27367+
4a4d8108 27368+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 27369+ && !au_opt_test(sbinfo->si_mntflags, XINO))
febd17d6 27370+ pr_warn_once("udba=*notify requires xino\n");
1facf9fc 27371+
076b876e 27372+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1))
febd17d6
JR
27373+ pr_warn_once("dirperm1 breaks the protection"
27374+ " by the permission bits on the lower branch\n");
076b876e 27375+
1facf9fc 27376+ err = 0;
076b876e 27377+ fhsm = 0;
1facf9fc 27378+ root = sb->s_root;
5527c038 27379+ dir = d_inode(root);
1facf9fc 27380+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
79b8bda9
AM
27381+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending),
27382+ UDBA_NONE);
5afbbe0d
AM
27383+ bbot = au_sbbot(sb);
27384+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
1facf9fc 27385+ skip = 0;
27386+ h_dir = au_h_iptr(dir, bindex);
27387+ br = au_sbr(sb, bindex);
1facf9fc 27388+
c1595e42
JR
27389+ if ((br->br_perm & AuBrAttr_ICEX)
27390+ && !h_dir->i_op->listxattr)
27391+ br->br_perm &= ~AuBrAttr_ICEX;
27392+#if 0
27393+ if ((br->br_perm & AuBrAttr_ICEX_SEC)
2121bcd9 27394+ && (au_br_sb(br)->s_flags & SB_NOSEC))
c1595e42
JR
27395+ br->br_perm &= ~AuBrAttr_ICEX_SEC;
27396+#endif
27397+
27398+ do_free = 0;
1facf9fc 27399+ wbr = br->br_wbr;
27400+ if (wbr)
27401+ wbr_wh_read_lock(wbr);
27402+
1e00d052 27403+ if (!au_br_writable(br->br_perm)) {
1facf9fc 27404+ do_free = !!wbr;
27405+ skip = (!wbr
27406+ || (!wbr->wbr_whbase
27407+ && !wbr->wbr_plink
27408+ && !wbr->wbr_orph));
1e00d052 27409+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 27410+ /* skip = (!br->br_whbase && !br->br_orph); */
27411+ skip = (!wbr || !wbr->wbr_whbase);
27412+ if (skip && wbr) {
27413+ if (do_plink)
27414+ skip = !!wbr->wbr_plink;
27415+ else
27416+ skip = !wbr->wbr_plink;
27417+ }
1e00d052 27418+ } else {
1facf9fc 27419+ /* skip = (br->br_whbase && br->br_ohph); */
27420+ skip = (wbr && wbr->wbr_whbase);
27421+ if (skip) {
27422+ if (do_plink)
27423+ skip = !!wbr->wbr_plink;
27424+ else
27425+ skip = !wbr->wbr_plink;
27426+ }
1facf9fc 27427+ }
27428+ if (wbr)
27429+ wbr_wh_read_unlock(wbr);
27430+
79b8bda9
AM
27431+ if (can_no_dreval) {
27432+ dentry = br->br_path.dentry;
27433+ spin_lock(&dentry->d_lock);
27434+ if (dentry->d_flags &
27435+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE))
27436+ can_no_dreval = 0;
27437+ spin_unlock(&dentry->d_lock);
27438+ }
27439+
076b876e
AM
27440+ if (au_br_fhsm(br->br_perm)) {
27441+ fhsm++;
27442+ AuDebugOn(!br->br_fhsm);
27443+ }
27444+
1facf9fc 27445+ if (skip)
27446+ continue;
27447+
27448+ hdir = au_hi(dir, bindex);
5afbbe0d 27449+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 27450+ if (wbr)
27451+ wbr_wh_write_lock(wbr);
86dc4139 27452+ err = au_wh_init(br, sb);
1facf9fc 27453+ if (wbr)
27454+ wbr_wh_write_unlock(wbr);
5afbbe0d 27455+ au_hn_inode_unlock(hdir);
1facf9fc 27456+
27457+ if (!err && do_free) {
9f237c51 27458+ au_kfree_rcu(wbr);
1facf9fc 27459+ br->br_wbr = NULL;
27460+ }
27461+ }
27462+
79b8bda9
AM
27463+ if (can_no_dreval)
27464+ au_fset_si(sbinfo, NO_DREVAL);
27465+ else
27466+ au_fclr_si(sbinfo, NO_DREVAL);
27467+
c1595e42 27468+ if (fhsm >= 2) {
076b876e 27469+ au_fset_si(sbinfo, FHSM);
5afbbe0d 27470+ for (bindex = bbot; bindex >= 0; bindex--) {
c1595e42
JR
27471+ br = au_sbr(sb, bindex);
27472+ if (au_br_fhsm(br->br_perm)) {
27473+ au_fhsm_set_bottom(sb, bindex);
27474+ break;
27475+ }
27476+ }
27477+ } else {
076b876e 27478+ au_fclr_si(sbinfo, FHSM);
c1595e42
JR
27479+ au_fhsm_set_bottom(sb, -1);
27480+ }
076b876e 27481+
1facf9fc 27482+ return err;
27483+}
27484+
27485+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
27486+{
27487+ int err;
27488+ unsigned int tmp;
5afbbe0d 27489+ aufs_bindex_t bindex, bbot;
1facf9fc 27490+ struct au_opt *opt;
27491+ struct au_opt_xino *opt_xino, xino;
27492+ struct au_sbinfo *sbinfo;
027c5e7a 27493+ struct au_branch *br;
076b876e 27494+ struct inode *dir;
1facf9fc 27495+
dece6358
AM
27496+ SiMustWriteLock(sb);
27497+
1facf9fc 27498+ err = 0;
27499+ opt_xino = NULL;
27500+ opt = opts->opt;
27501+ while (err >= 0 && opt->type != Opt_tail)
27502+ err = au_opt_simple(sb, opt++, opts);
27503+ if (err > 0)
27504+ err = 0;
27505+ else if (unlikely(err < 0))
27506+ goto out;
27507+
27508+ /* disable xino and udba temporary */
27509+ sbinfo = au_sbi(sb);
27510+ tmp = sbinfo->si_mntflags;
27511+ au_opt_clr(sbinfo->si_mntflags, XINO);
27512+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
27513+
27514+ opt = opts->opt;
27515+ while (err >= 0 && opt->type != Opt_tail)
27516+ err = au_opt_br(sb, opt++, opts);
27517+ if (err > 0)
27518+ err = 0;
27519+ else if (unlikely(err < 0))
27520+ goto out;
27521+
5afbbe0d
AM
27522+ bbot = au_sbbot(sb);
27523+ if (unlikely(bbot < 0)) {
1facf9fc 27524+ err = -EINVAL;
4a4d8108 27525+ pr_err("no branches\n");
1facf9fc 27526+ goto out;
27527+ }
27528+
27529+ if (au_opt_test(tmp, XINO))
27530+ au_opt_set(sbinfo->si_mntflags, XINO);
27531+ opt = opts->opt;
27532+ while (!err && opt->type != Opt_tail)
27533+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
27534+ if (unlikely(err))
27535+ goto out;
27536+
27537+ err = au_opts_verify(sb, sb->s_flags, tmp);
27538+ if (unlikely(err))
27539+ goto out;
27540+
27541+ /* restore xino */
27542+ if (au_opt_test(tmp, XINO) && !opt_xino) {
27543+ xino.file = au_xino_def(sb);
27544+ err = PTR_ERR(xino.file);
27545+ if (IS_ERR(xino.file))
27546+ goto out;
27547+
27548+ err = au_xino_set(sb, &xino, /*remount*/0);
27549+ fput(xino.file);
27550+ if (unlikely(err))
27551+ goto out;
27552+ }
27553+
27554+ /* restore udba */
027c5e7a 27555+ tmp &= AuOptMask_UDBA;
1facf9fc 27556+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a 27557+ sbinfo->si_mntflags |= tmp;
5afbbe0d
AM
27558+ bbot = au_sbbot(sb);
27559+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
27560+ br = au_sbr(sb, bindex);
27561+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
27562+ if (unlikely(err))
27563+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
27564+ bindex, err);
27565+ /* go on even if err */
27566+ }
4a4d8108 27567+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
5527c038 27568+ dir = d_inode(sb->s_root);
4a4d8108 27569+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 27570+ }
27571+
4f0767ce 27572+out:
1facf9fc 27573+ return err;
27574+}
27575+
27576+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
27577+{
27578+ int err, rerr;
79b8bda9 27579+ unsigned char no_dreval;
1facf9fc 27580+ struct inode *dir;
27581+ struct au_opt_xino *opt_xino;
27582+ struct au_opt *opt;
27583+ struct au_sbinfo *sbinfo;
27584+
dece6358
AM
27585+ SiMustWriteLock(sb);
27586+
8b6a4947
AM
27587+ err = au_dr_opt_flush(sb);
27588+ if (unlikely(err))
27589+ goto out;
27590+ au_fset_opts(opts->flags, DR_FLUSHED);
27591+
5527c038 27592+ dir = d_inode(sb->s_root);
1facf9fc 27593+ sbinfo = au_sbi(sb);
1facf9fc 27594+ opt_xino = NULL;
27595+ opt = opts->opt;
27596+ while (err >= 0 && opt->type != Opt_tail) {
27597+ err = au_opt_simple(sb, opt, opts);
27598+ if (!err)
27599+ err = au_opt_br(sb, opt, opts);
27600+ if (!err)
27601+ err = au_opt_xino(sb, opt, &opt_xino, opts);
27602+ opt++;
27603+ }
27604+ if (err > 0)
27605+ err = 0;
27606+ AuTraceErr(err);
27607+ /* go on even err */
27608+
79b8bda9 27609+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
1facf9fc 27610+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
27611+ if (unlikely(rerr && !err))
27612+ err = rerr;
27613+
79b8bda9 27614+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
b95c5147 27615+ au_fset_opts(opts->flags, REFRESH_IDOP);
79b8bda9 27616+
1facf9fc 27617+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
27618+ rerr = au_xib_trunc(sb);
27619+ if (unlikely(rerr && !err))
27620+ err = rerr;
27621+ }
27622+
27623+ /* will be handled by the caller */
027c5e7a 27624+ if (!au_ftest_opts(opts->flags, REFRESH)
79b8bda9
AM
27625+ && (opts->given_udba
27626+ || au_opt_test(sbinfo->si_mntflags, XINO)
b95c5147 27627+ || au_ftest_opts(opts->flags, REFRESH_IDOP)
79b8bda9 27628+ ))
027c5e7a 27629+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27630+
27631+ AuDbg("status 0x%x\n", opts->flags);
8b6a4947
AM
27632+
27633+out:
1facf9fc 27634+ return err;
27635+}
27636+
27637+/* ---------------------------------------------------------------------- */
27638+
27639+unsigned int au_opt_udba(struct super_block *sb)
27640+{
27641+ return au_mntflags(sb) & AuOptMask_UDBA;
27642+}
7f207e10 27643diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
eca34b5c
AM
27644--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
27645+++ linux/fs/aufs/opts.h 2019-07-11 15:42:14.472238057 +0200
062440b3
AM
27646@@ -0,0 +1,225 @@
27647+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 27648+/*
ba1aed25 27649+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 27650+ *
27651+ * This program, aufs is free software; you can redistribute it and/or modify
27652+ * it under the terms of the GNU General Public License as published by
27653+ * the Free Software Foundation; either version 2 of the License, or
27654+ * (at your option) any later version.
dece6358
AM
27655+ *
27656+ * This program is distributed in the hope that it will be useful,
27657+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27658+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27659+ * GNU General Public License for more details.
27660+ *
27661+ * You should have received a copy of the GNU General Public License
523b37e3 27662+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27663+ */
27664+
27665+/*
27666+ * mount options/flags
27667+ */
27668+
27669+#ifndef __AUFS_OPTS_H__
27670+#define __AUFS_OPTS_H__
27671+
27672+#ifdef __KERNEL__
27673+
dece6358 27674+#include <linux/path.h>
1facf9fc 27675+
dece6358 27676+struct file;
dece6358 27677+
1facf9fc 27678+/* ---------------------------------------------------------------------- */
27679+
27680+/* mount flags */
27681+#define AuOpt_XINO 1 /* external inode number bitmap
27682+ and translation table */
27683+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
27684+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
27685+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 27686+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
27687+#define AuOpt_SHWH (1 << 5) /* show whiteout */
27688+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
076b876e
AM
27689+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm
27690+ bits */
dece6358
AM
27691+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
27692+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
27693+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
27694+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
eca801bf 27695+#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */
4a4d8108 27696+#define AuOpt_DIO (1 << 14) /* direct io */
8b6a4947 27697+#define AuOpt_DIRREN (1 << 15) /* directory rename */
1facf9fc 27698+
4a4d8108
AM
27699+#ifndef CONFIG_AUFS_HNOTIFY
27700+#undef AuOpt_UDBA_HNOTIFY
27701+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 27702+#endif
8b6a4947
AM
27703+#ifndef CONFIG_AUFS_DIRREN
27704+#undef AuOpt_DIRREN
27705+#define AuOpt_DIRREN 0
27706+#endif
dece6358
AM
27707+#ifndef CONFIG_AUFS_SHWH
27708+#undef AuOpt_SHWH
27709+#define AuOpt_SHWH 0
27710+#endif
1facf9fc 27711+
27712+#define AuOpt_Def (AuOpt_XINO \
27713+ | AuOpt_UDBA_REVAL \
27714+ | AuOpt_PLINK \
27715+ /* | AuOpt_DIRPERM1 */ \
27716+ | AuOpt_WARN_PERM)
27717+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
27718+ | AuOpt_UDBA_REVAL \
4a4d8108 27719+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 27720+
27721+#define au_opt_test(flags, name) (flags & AuOpt_##name)
27722+#define au_opt_set(flags, name) do { \
27723+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
27724+ ((flags) |= AuOpt_##name); \
27725+} while (0)
27726+#define au_opt_set_udba(flags, name) do { \
27727+ (flags) &= ~AuOptMask_UDBA; \
27728+ ((flags) |= AuOpt_##name); \
27729+} while (0)
7f207e10
AM
27730+#define au_opt_clr(flags, name) do { \
27731+ ((flags) &= ~AuOpt_##name); \
27732+} while (0)
1facf9fc 27733+
e49829fe
JR
27734+static inline unsigned int au_opts_plink(unsigned int mntflags)
27735+{
27736+#ifdef CONFIG_PROC_FS
27737+ return mntflags;
27738+#else
27739+ return mntflags & ~AuOpt_PLINK;
27740+#endif
27741+}
27742+
1facf9fc 27743+/* ---------------------------------------------------------------------- */
27744+
27745+/* policies to select one among multiple writable branches */
27746+enum {
27747+ AuWbrCreate_TDP, /* top down parent */
27748+ AuWbrCreate_RR, /* round robin */
27749+ AuWbrCreate_MFS, /* most free space */
27750+ AuWbrCreate_MFSV, /* mfs with seconds */
27751+ AuWbrCreate_MFSRR, /* mfs then rr */
27752+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
f2c43d5f
AM
27753+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */
27754+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */
1facf9fc 27755+ AuWbrCreate_PMFS, /* parent and mfs */
27756+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
392086de
AM
27757+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */
27758+ AuWbrCreate_PMFSRRV, /* plus seconds */
1facf9fc 27759+
27760+ AuWbrCreate_Def = AuWbrCreate_TDP
27761+};
27762+
27763+enum {
27764+ AuWbrCopyup_TDP, /* top down parent */
27765+ AuWbrCopyup_BUP, /* bottom up parent */
27766+ AuWbrCopyup_BU, /* bottom up */
27767+
27768+ AuWbrCopyup_Def = AuWbrCopyup_TDP
27769+};
27770+
27771+/* ---------------------------------------------------------------------- */
27772+
27773+struct au_opt_add {
27774+ aufs_bindex_t bindex;
27775+ char *pathname;
27776+ int perm;
27777+ struct path path;
27778+};
27779+
27780+struct au_opt_del {
27781+ char *pathname;
27782+ struct path h_path;
27783+};
27784+
27785+struct au_opt_mod {
27786+ char *path;
27787+ int perm;
27788+ struct dentry *h_root;
27789+};
27790+
27791+struct au_opt_xino {
27792+ char *path;
27793+ struct file *file;
27794+};
27795+
27796+struct au_opt_xino_itrunc {
27797+ aufs_bindex_t bindex;
27798+};
27799+
27800+struct au_opt_wbr_create {
27801+ int wbr_create;
27802+ int mfs_second;
27803+ unsigned long long mfsrr_watermark;
27804+};
27805+
27806+struct au_opt {
27807+ int type;
27808+ union {
27809+ struct au_opt_xino xino;
27810+ struct au_opt_xino_itrunc xino_itrunc;
27811+ struct au_opt_add add;
27812+ struct au_opt_del del;
27813+ struct au_opt_mod mod;
27814+ int dirwh;
27815+ int rdcache;
27816+ unsigned int rdblk;
27817+ unsigned int rdhash;
27818+ int udba;
27819+ struct au_opt_wbr_create wbr_create;
27820+ int wbr_copyup;
076b876e 27821+ unsigned int fhsm_second;
1facf9fc 27822+ };
27823+};
27824+
27825+/* opts flags */
27826+#define AuOpts_REMOUNT 1
027c5e7a
AM
27827+#define AuOpts_REFRESH (1 << 1)
27828+#define AuOpts_TRUNC_XIB (1 << 2)
27829+#define AuOpts_REFRESH_DYAOP (1 << 3)
b95c5147 27830+#define AuOpts_REFRESH_IDOP (1 << 4)
8b6a4947 27831+#define AuOpts_DR_FLUSHED (1 << 5)
1facf9fc 27832+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
27833+#define au_fset_opts(flags, name) \
27834+ do { (flags) |= AuOpts_##name; } while (0)
27835+#define au_fclr_opts(flags, name) \
27836+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 27837+
8b6a4947
AM
27838+#ifndef CONFIG_AUFS_DIRREN
27839+#undef AuOpts_DR_FLUSHED
27840+#define AuOpts_DR_FLUSHED 0
27841+#endif
27842+
1facf9fc 27843+struct au_opts {
27844+ struct au_opt *opt;
27845+ int max_opt;
27846+
27847+ unsigned int given_udba;
27848+ unsigned int flags;
27849+ unsigned long sb_flags;
27850+};
27851+
27852+/* ---------------------------------------------------------------------- */
27853+
7e9cd9fe 27854+/* opts.c */
076b876e 27855+void au_optstr_br_perm(au_br_perm_str_t *str, int perm);
1facf9fc 27856+const char *au_optstr_udba(int udba);
27857+const char *au_optstr_wbr_copyup(int wbr_copyup);
27858+const char *au_optstr_wbr_create(int wbr_create);
27859+
27860+void au_opts_free(struct au_opts *opts);
3c1bdaff 27861+struct super_block;
1facf9fc 27862+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
27863+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27864+ unsigned int pending);
27865+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
27866+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
27867+
27868+unsigned int au_opt_udba(struct super_block *sb);
27869+
1facf9fc 27870+#endif /* __KERNEL__ */
27871+#endif /* __AUFS_OPTS_H__ */
7f207e10 27872diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
eca34b5c
AM
27873--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
27874+++ linux/fs/aufs/plink.c 2019-07-11 15:42:14.472238057 +0200
062440b3 27875@@ -0,0 +1,516 @@
cd7a4cd9 27876+// SPDX-License-Identifier: GPL-2.0
1facf9fc 27877+/*
ba1aed25 27878+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 27879+ *
27880+ * This program, aufs is free software; you can redistribute it and/or modify
27881+ * it under the terms of the GNU General Public License as published by
27882+ * the Free Software Foundation; either version 2 of the License, or
27883+ * (at your option) any later version.
dece6358
AM
27884+ *
27885+ * This program is distributed in the hope that it will be useful,
27886+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27887+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27888+ * GNU General Public License for more details.
27889+ *
27890+ * You should have received a copy of the GNU General Public License
523b37e3 27891+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27892+ */
27893+
27894+/*
27895+ * pseudo-link
27896+ */
27897+
27898+#include "aufs.h"
27899+
27900+/*
e49829fe 27901+ * the pseudo-link maintenance mode.
1facf9fc 27902+ * during a user process maintains the pseudo-links,
27903+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
27904+ *
27905+ * Flags
27906+ * NOPLM:
27907+ * For entry functions which will handle plink, and i_mutex is already held
27908+ * in VFS.
27909+ * They cannot wait and should return an error at once.
27910+ * Callers has to check the error.
27911+ * NOPLMW:
27912+ * For entry functions which will handle plink, but i_mutex is not held
27913+ * in VFS.
27914+ * They can wait the plink maintenance mode to finish.
27915+ *
27916+ * They behave like F_SETLK and F_SETLKW.
27917+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 27918+ */
e49829fe
JR
27919+
27920+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 27921+{
e49829fe
JR
27922+ int err;
27923+ pid_t pid, ppid;
f0c0a007 27924+ struct task_struct *parent, *prev;
e49829fe 27925+ struct au_sbinfo *sbi;
dece6358
AM
27926+
27927+ SiMustAnyLock(sb);
27928+
e49829fe
JR
27929+ err = 0;
27930+ if (!au_opt_test(au_mntflags(sb), PLINK))
27931+ goto out;
27932+
27933+ sbi = au_sbi(sb);
27934+ pid = sbi->si_plink_maint_pid;
27935+ if (!pid || pid == current->pid)
27936+ goto out;
27937+
27938+ /* todo: it highly depends upon /sbin/mount.aufs */
f0c0a007
AM
27939+ prev = NULL;
27940+ parent = current;
27941+ ppid = 0;
e49829fe 27942+ rcu_read_lock();
f0c0a007
AM
27943+ while (1) {
27944+ parent = rcu_dereference(parent->real_parent);
27945+ if (parent == prev)
27946+ break;
27947+ ppid = task_pid_vnr(parent);
27948+ if (pid == ppid) {
27949+ rcu_read_unlock();
27950+ goto out;
27951+ }
27952+ prev = parent;
27953+ }
e49829fe 27954+ rcu_read_unlock();
e49829fe
JR
27955+
27956+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
27957+ /* if there is no i_mutex lock in VFS, we don't need to wait */
27958+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
27959+ while (sbi->si_plink_maint_pid) {
27960+ si_read_unlock(sb);
27961+ /* gave up wake_up_bit() */
27962+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
27963+
27964+ if (au_ftest_lock(flags, FLUSH))
27965+ au_nwt_flush(&sbi->si_nowait);
27966+ si_noflush_read_lock(sb);
27967+ }
27968+ } else if (au_ftest_lock(flags, NOPLM)) {
27969+ AuDbg("ppid %d, pid %d\n", ppid, pid);
27970+ err = -EAGAIN;
27971+ }
27972+
27973+out:
27974+ return err;
4a4d8108
AM
27975+}
27976+
e49829fe 27977+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 27978+{
4a4d8108 27979+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 27980+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 27981+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 27982+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
27983+}
27984+
e49829fe 27985+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
27986+{
27987+ int err;
4a4d8108
AM
27988+ struct au_sbinfo *sbinfo;
27989+
27990+ err = 0;
4a4d8108
AM
27991+ sbinfo = au_sbi(sb);
27992+ /* make sure i am the only one in this fs */
e49829fe
JR
27993+ si_write_lock(sb, AuLock_FLUSH);
27994+ if (au_opt_test(au_mntflags(sb), PLINK)) {
27995+ spin_lock(&sbinfo->si_plink_maint_lock);
27996+ if (!sbinfo->si_plink_maint_pid)
27997+ sbinfo->si_plink_maint_pid = current->pid;
27998+ else
27999+ err = -EBUSY;
28000+ spin_unlock(&sbinfo->si_plink_maint_lock);
28001+ }
4a4d8108
AM
28002+ si_write_unlock(sb);
28003+
28004+ return err;
1facf9fc 28005+}
28006+
28007+/* ---------------------------------------------------------------------- */
28008+
1facf9fc 28009+#ifdef CONFIG_AUFS_DEBUG
28010+void au_plink_list(struct super_block *sb)
28011+{
86dc4139 28012+ int i;
1facf9fc 28013+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28014+ struct hlist_bl_head *hbl;
28015+ struct hlist_bl_node *pos;
5afbbe0d 28016+ struct au_icntnr *icntnr;
1facf9fc 28017+
dece6358
AM
28018+ SiMustAnyLock(sb);
28019+
1facf9fc 28020+ sbinfo = au_sbi(sb);
28021+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28022+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28023+
86dc4139 28024+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28025+ hbl = sbinfo->si_plink + i;
28026+ hlist_bl_lock(hbl);
28027+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 28028+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino);
8b6a4947 28029+ hlist_bl_unlock(hbl);
86dc4139 28030+ }
1facf9fc 28031+}
28032+#endif
28033+
28034+/* is the inode pseudo-linked? */
28035+int au_plink_test(struct inode *inode)
28036+{
86dc4139 28037+ int found, i;
1facf9fc 28038+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28039+ struct hlist_bl_head *hbl;
28040+ struct hlist_bl_node *pos;
5afbbe0d 28041+ struct au_icntnr *icntnr;
1facf9fc 28042+
28043+ sbinfo = au_sbi(inode->i_sb);
dece6358 28044+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 28045+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 28046+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 28047+
28048+ found = 0;
86dc4139 28049+ i = au_plink_hash(inode->i_ino);
8b6a4947
AM
28050+ hbl = sbinfo->si_plink + i;
28051+ hlist_bl_lock(hbl);
28052+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 28053+ if (&icntnr->vfs_inode == inode) {
1facf9fc 28054+ found = 1;
28055+ break;
28056+ }
8b6a4947 28057+ hlist_bl_unlock(hbl);
1facf9fc 28058+ return found;
28059+}
28060+
28061+/* ---------------------------------------------------------------------- */
28062+
28063+/*
28064+ * generate a name for plink.
28065+ * the file will be stored under AUFS_WH_PLINKDIR.
28066+ */
28067+/* 20 is max digits length of ulong 64 */
28068+#define PLINK_NAME_LEN ((20 + 1) * 2)
28069+
28070+static int plink_name(char *name, int len, struct inode *inode,
28071+ aufs_bindex_t bindex)
28072+{
28073+ int rlen;
28074+ struct inode *h_inode;
28075+
28076+ h_inode = au_h_iptr(inode, bindex);
28077+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
28078+ return rlen;
28079+}
28080+
7f207e10
AM
28081+struct au_do_plink_lkup_args {
28082+ struct dentry **errp;
28083+ struct qstr *tgtname;
28084+ struct dentry *h_parent;
28085+ struct au_branch *br;
28086+};
28087+
28088+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
28089+ struct dentry *h_parent,
28090+ struct au_branch *br)
28091+{
28092+ struct dentry *h_dentry;
febd17d6 28093+ struct inode *h_inode;
7f207e10 28094+
febd17d6 28095+ h_inode = d_inode(h_parent);
be118d29 28096+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2);
b4510431 28097+ h_dentry = vfsub_lkup_one(tgtname, h_parent);
3c1bdaff 28098+ inode_unlock_shared(h_inode);
7f207e10
AM
28099+ return h_dentry;
28100+}
28101+
28102+static void au_call_do_plink_lkup(void *args)
28103+{
28104+ struct au_do_plink_lkup_args *a = args;
28105+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
28106+}
28107+
1facf9fc 28108+/* lookup the plink-ed @inode under the branch at @bindex */
28109+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
28110+{
28111+ struct dentry *h_dentry, *h_parent;
28112+ struct au_branch *br;
7f207e10 28113+ int wkq_err;
1facf9fc 28114+ char a[PLINK_NAME_LEN];
0c3ec466 28115+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 28116+
e49829fe
JR
28117+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
28118+
1facf9fc 28119+ br = au_sbr(inode->i_sb, bindex);
28120+ h_parent = br->br_wbr->wbr_plink;
1facf9fc 28121+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
28122+
2dfbb274 28123+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
28124+ struct au_do_plink_lkup_args args = {
28125+ .errp = &h_dentry,
28126+ .tgtname = &tgtname,
28127+ .h_parent = h_parent,
28128+ .br = br
28129+ };
28130+
28131+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
28132+ if (unlikely(wkq_err))
28133+ h_dentry = ERR_PTR(wkq_err);
28134+ } else
28135+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
28136+
1facf9fc 28137+ return h_dentry;
28138+}
28139+
28140+/* create a pseudo-link */
28141+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
28142+ struct dentry *h_dentry, struct au_branch *br)
28143+{
28144+ int err;
28145+ struct path h_path = {
86dc4139 28146+ .mnt = au_br_mnt(br)
1facf9fc 28147+ };
523b37e3 28148+ struct inode *h_dir, *delegated;
1facf9fc 28149+
5527c038 28150+ h_dir = d_inode(h_parent);
febd17d6 28151+ inode_lock_nested(h_dir, AuLsc_I_CHILD2);
4f0767ce 28152+again:
b4510431 28153+ h_path.dentry = vfsub_lkup_one(tgt, h_parent);
1facf9fc 28154+ err = PTR_ERR(h_path.dentry);
28155+ if (IS_ERR(h_path.dentry))
28156+ goto out;
28157+
28158+ err = 0;
28159+ /* wh.plink dir is not monitored */
7f207e10 28160+ /* todo: is it really safe? */
5527c038
JR
28161+ if (d_is_positive(h_path.dentry)
28162+ && d_inode(h_path.dentry) != d_inode(h_dentry)) {
523b37e3
AM
28163+ delegated = NULL;
28164+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0);
28165+ if (unlikely(err == -EWOULDBLOCK)) {
28166+ pr_warn("cannot retry for NFSv4 delegation"
28167+ " for an internal unlink\n");
28168+ iput(delegated);
28169+ }
1facf9fc 28170+ dput(h_path.dentry);
28171+ h_path.dentry = NULL;
28172+ if (!err)
28173+ goto again;
28174+ }
5527c038 28175+ if (!err && d_is_negative(h_path.dentry)) {
523b37e3
AM
28176+ delegated = NULL;
28177+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated);
28178+ if (unlikely(err == -EWOULDBLOCK)) {
28179+ pr_warn("cannot retry for NFSv4 delegation"
28180+ " for an internal link\n");
28181+ iput(delegated);
28182+ }
28183+ }
1facf9fc 28184+ dput(h_path.dentry);
28185+
4f0767ce 28186+out:
febd17d6 28187+ inode_unlock(h_dir);
1facf9fc 28188+ return err;
28189+}
28190+
28191+struct do_whplink_args {
28192+ int *errp;
28193+ struct qstr *tgt;
28194+ struct dentry *h_parent;
28195+ struct dentry *h_dentry;
28196+ struct au_branch *br;
28197+};
28198+
28199+static void call_do_whplink(void *args)
28200+{
28201+ struct do_whplink_args *a = args;
28202+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
28203+}
28204+
28205+static int whplink(struct dentry *h_dentry, struct inode *inode,
28206+ aufs_bindex_t bindex, struct au_branch *br)
28207+{
28208+ int err, wkq_err;
28209+ struct au_wbr *wbr;
28210+ struct dentry *h_parent;
1facf9fc 28211+ char a[PLINK_NAME_LEN];
0c3ec466 28212+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 28213+
28214+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
28215+ h_parent = wbr->wbr_plink;
1facf9fc 28216+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
28217+
28218+ /* always superio. */
2dfbb274 28219+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 28220+ struct do_whplink_args args = {
28221+ .errp = &err,
28222+ .tgt = &tgtname,
28223+ .h_parent = h_parent,
28224+ .h_dentry = h_dentry,
28225+ .br = br
28226+ };
28227+ wkq_err = au_wkq_wait(call_do_whplink, &args);
28228+ if (unlikely(wkq_err))
28229+ err = wkq_err;
28230+ } else
28231+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 28232+
28233+ return err;
28234+}
28235+
1facf9fc 28236+/*
28237+ * create a new pseudo-link for @h_dentry on @bindex.
28238+ * the linked inode is held in aufs @inode.
28239+ */
28240+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
28241+ struct dentry *h_dentry)
28242+{
28243+ struct super_block *sb;
28244+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28245+ struct hlist_bl_head *hbl;
28246+ struct hlist_bl_node *pos;
5afbbe0d 28247+ struct au_icntnr *icntnr;
86dc4139 28248+ int found, err, cnt, i;
1facf9fc 28249+
28250+ sb = inode->i_sb;
28251+ sbinfo = au_sbi(sb);
28252+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28253+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28254+
86dc4139 28255+ found = au_plink_test(inode);
4a4d8108 28256+ if (found)
1facf9fc 28257+ return;
4a4d8108 28258+
86dc4139 28259+ i = au_plink_hash(inode->i_ino);
8b6a4947 28260+ hbl = sbinfo->si_plink + i;
5afbbe0d 28261+ au_igrab(inode);
1facf9fc 28262+
8b6a4947
AM
28263+ hlist_bl_lock(hbl);
28264+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) {
5afbbe0d 28265+ if (&icntnr->vfs_inode == inode) {
4a4d8108
AM
28266+ found = 1;
28267+ break;
28268+ }
1facf9fc 28269+ }
5afbbe0d
AM
28270+ if (!found) {
28271+ icntnr = container_of(inode, struct au_icntnr, vfs_inode);
8b6a4947 28272+ hlist_bl_add_head(&icntnr->plink, hbl);
5afbbe0d 28273+ }
8b6a4947 28274+ hlist_bl_unlock(hbl);
4a4d8108 28275+ if (!found) {
8b6a4947 28276+ cnt = au_hbl_count(hbl);
acd2b654 28277+#define msg "unexpectedly unbalanced or too many pseudo-links"
86dc4139
AM
28278+ if (cnt > AUFS_PLINK_WARN)
28279+ AuWarn1(msg ", %d\n", cnt);
28280+#undef msg
1facf9fc 28281+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
5afbbe0d
AM
28282+ if (unlikely(err)) {
28283+ pr_warn("err %d, damaged pseudo link.\n", err);
8b6a4947 28284+ au_hbl_del(&icntnr->plink, hbl);
5afbbe0d 28285+ iput(&icntnr->vfs_inode);
4a4d8108 28286+ }
5afbbe0d
AM
28287+ } else
28288+ iput(&icntnr->vfs_inode);
1facf9fc 28289+}
28290+
28291+/* free all plinks */
e49829fe 28292+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 28293+{
86dc4139 28294+ int i, warned;
1facf9fc 28295+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28296+ struct hlist_bl_head *hbl;
28297+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28298+ struct au_icntnr *icntnr;
1facf9fc 28299+
dece6358
AM
28300+ SiMustWriteLock(sb);
28301+
1facf9fc 28302+ sbinfo = au_sbi(sb);
28303+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28304+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28305+
1facf9fc 28306+ /* no spin_lock since sbinfo is write-locked */
86dc4139
AM
28307+ warned = 0;
28308+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28309+ hbl = sbinfo->si_plink + i;
28310+ if (!warned && verbose && !hlist_bl_empty(hbl)) {
86dc4139
AM
28311+ pr_warn("pseudo-link is not flushed");
28312+ warned = 1;
28313+ }
8b6a4947 28314+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink)
5afbbe0d 28315+ iput(&icntnr->vfs_inode);
8b6a4947 28316+ INIT_HLIST_BL_HEAD(hbl);
86dc4139 28317+ }
1facf9fc 28318+}
28319+
e49829fe
JR
28320+void au_plink_clean(struct super_block *sb, int verbose)
28321+{
28322+ struct dentry *root;
28323+
28324+ root = sb->s_root;
28325+ aufs_write_lock(root);
28326+ if (au_opt_test(au_mntflags(sb), PLINK))
28327+ au_plink_put(sb, verbose);
28328+ aufs_write_unlock(root);
28329+}
28330+
86dc4139
AM
28331+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id)
28332+{
28333+ int do_put;
5afbbe0d 28334+ aufs_bindex_t btop, bbot, bindex;
86dc4139
AM
28335+
28336+ do_put = 0;
5afbbe0d
AM
28337+ btop = au_ibtop(inode);
28338+ bbot = au_ibbot(inode);
28339+ if (btop >= 0) {
28340+ for (bindex = btop; bindex <= bbot; bindex++) {
86dc4139
AM
28341+ if (!au_h_iptr(inode, bindex)
28342+ || au_ii_br_id(inode, bindex) != br_id)
28343+ continue;
28344+ au_set_h_iptr(inode, bindex, NULL, 0);
28345+ do_put = 1;
28346+ break;
28347+ }
28348+ if (do_put)
5afbbe0d 28349+ for (bindex = btop; bindex <= bbot; bindex++)
86dc4139
AM
28350+ if (au_h_iptr(inode, bindex)) {
28351+ do_put = 0;
28352+ break;
28353+ }
28354+ } else
28355+ do_put = 1;
28356+
28357+ return do_put;
28358+}
28359+
1facf9fc 28360+/* free the plinks on a branch specified by @br_id */
28361+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
28362+{
28363+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28364+ struct hlist_bl_head *hbl;
28365+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28366+ struct au_icntnr *icntnr;
1facf9fc 28367+ struct inode *inode;
86dc4139 28368+ int i, do_put;
1facf9fc 28369+
dece6358
AM
28370+ SiMustWriteLock(sb);
28371+
1facf9fc 28372+ sbinfo = au_sbi(sb);
28373+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28374+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28375+
8b6a4947 28376+ /* no bit_lock since sbinfo is write-locked */
86dc4139 28377+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28378+ hbl = sbinfo->si_plink + i;
28379+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) {
5afbbe0d 28380+ inode = au_igrab(&icntnr->vfs_inode);
86dc4139
AM
28381+ ii_write_lock_child(inode);
28382+ do_put = au_plink_do_half_refresh(inode, br_id);
5afbbe0d 28383+ if (do_put) {
8b6a4947 28384+ hlist_bl_del(&icntnr->plink);
5afbbe0d
AM
28385+ iput(inode);
28386+ }
86dc4139
AM
28387+ ii_write_unlock(inode);
28388+ iput(inode);
dece6358 28389+ }
dece6358
AM
28390+ }
28391+}
7f207e10 28392diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
eca34b5c
AM
28393--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
28394+++ linux/fs/aufs/poll.c 2019-07-11 15:42:14.472238057 +0200
cd7a4cd9
AM
28395@@ -0,0 +1,51 @@
28396+// SPDX-License-Identifier: GPL-2.0
dece6358 28397+/*
ba1aed25 28398+ * Copyright (C) 2005-2019 Junjiro R. Okajima
dece6358
AM
28399+ *
28400+ * This program, aufs is free software; you can redistribute it and/or modify
28401+ * it under the terms of the GNU General Public License as published by
28402+ * the Free Software Foundation; either version 2 of the License, or
28403+ * (at your option) any later version.
28404+ *
28405+ * This program is distributed in the hope that it will be useful,
28406+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28407+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28408+ * GNU General Public License for more details.
28409+ *
28410+ * You should have received a copy of the GNU General Public License
523b37e3 28411+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358
AM
28412+ */
28413+
1308ab2a 28414+/*
28415+ * poll operation
28416+ * There is only one filesystem which implements ->poll operation, currently.
28417+ */
28418+
28419+#include "aufs.h"
28420+
cd7a4cd9 28421+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt)
1308ab2a 28422+{
be118d29 28423+ __poll_t mask;
1308ab2a 28424+ struct file *h_file;
1308ab2a 28425+ struct super_block *sb;
28426+
28427+ /* We should pretend an error happened. */
be118d29 28428+ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */;
b912730e 28429+ sb = file->f_path.dentry->d_sb;
e49829fe 28430+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 28431+
521ced18 28432+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
062440b3
AM
28433+ if (IS_ERR(h_file)) {
28434+ AuDbg("h_file %ld\n", PTR_ERR(h_file));
1308ab2a 28435+ goto out;
062440b3 28436+ }
1308ab2a 28437+
cd7a4cd9 28438+ mask = vfs_poll(h_file, pt);
b912730e 28439+ fput(h_file); /* instead of au_read_post() */
1308ab2a 28440+
4f0767ce 28441+out:
1308ab2a 28442+ si_read_unlock(sb);
062440b3 28443+ if (mask & EPOLLERR)
b00004a5 28444+ AuDbg("mask 0x%x\n", mask);
1308ab2a 28445+ return mask;
28446+}
c1595e42 28447diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c
eca34b5c
AM
28448--- /usr/share/empty/fs/aufs/posix_acl.c 1970-01-01 01:00:00.000000000 +0100
28449+++ linux/fs/aufs/posix_acl.c 2019-07-11 15:42:14.472238057 +0200
062440b3 28450@@ -0,0 +1,103 @@
cd7a4cd9 28451+// SPDX-License-Identifier: GPL-2.0
c1595e42 28452+/*
ba1aed25 28453+ * Copyright (C) 2014-2019 Junjiro R. Okajima
c1595e42
JR
28454+ *
28455+ * This program, aufs is free software; you can redistribute it and/or modify
28456+ * it under the terms of the GNU General Public License as published by
28457+ * the Free Software Foundation; either version 2 of the License, or
28458+ * (at your option) any later version.
28459+ *
28460+ * This program is distributed in the hope that it will be useful,
28461+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28462+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28463+ * GNU General Public License for more details.
28464+ *
28465+ * You should have received a copy of the GNU General Public License
28466+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
28467+ */
28468+
28469+/*
28470+ * posix acl operations
28471+ */
28472+
28473+#include <linux/fs.h>
c1595e42
JR
28474+#include "aufs.h"
28475+
28476+struct posix_acl *aufs_get_acl(struct inode *inode, int type)
28477+{
28478+ struct posix_acl *acl;
28479+ int err;
28480+ aufs_bindex_t bindex;
28481+ struct inode *h_inode;
28482+ struct super_block *sb;
28483+
28484+ acl = NULL;
28485+ sb = inode->i_sb;
28486+ si_read_lock(sb, AuLock_FLUSH);
28487+ ii_read_lock_child(inode);
2121bcd9 28488+ if (!(sb->s_flags & SB_POSIXACL))
c1595e42
JR
28489+ goto out;
28490+
5afbbe0d 28491+ bindex = au_ibtop(inode);
c1595e42
JR
28492+ h_inode = au_h_iptr(inode, bindex);
28493+ if (unlikely(!h_inode
28494+ || ((h_inode->i_mode & S_IFMT)
28495+ != (inode->i_mode & S_IFMT)))) {
28496+ err = au_busy_or_stale();
28497+ acl = ERR_PTR(err);
28498+ goto out;
28499+ }
28500+
28501+ /* always topmost only */
28502+ acl = get_acl(h_inode, type);
a2654f78
AM
28503+ if (!IS_ERR_OR_NULL(acl))
28504+ set_cached_acl(inode, type, acl);
c1595e42
JR
28505+
28506+out:
28507+ ii_read_unlock(inode);
28508+ si_read_unlock(sb);
28509+
28510+ AuTraceErrPtr(acl);
28511+ return acl;
28512+}
28513+
28514+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
28515+{
28516+ int err;
28517+ ssize_t ssz;
28518+ struct dentry *dentry;
f2c43d5f 28519+ struct au_sxattr arg = {
c1595e42
JR
28520+ .type = AU_ACL_SET,
28521+ .u.acl_set = {
28522+ .acl = acl,
28523+ .type = type
28524+ },
28525+ };
28526+
5afbbe0d
AM
28527+ IMustLock(inode);
28528+
c1595e42
JR
28529+ if (inode->i_ino == AUFS_ROOT_INO)
28530+ dentry = dget(inode->i_sb->s_root);
28531+ else {
28532+ dentry = d_find_alias(inode);
28533+ if (!dentry)
28534+ dentry = d_find_any_alias(inode);
28535+ if (!dentry) {
28536+ pr_warn("cannot handle this inode, "
28537+ "please report to aufs-users ML\n");
28538+ err = -ENOENT;
28539+ goto out;
28540+ }
28541+ }
28542+
f2c43d5f 28543+ ssz = au_sxattr(dentry, inode, &arg);
c1595e42
JR
28544+ dput(dentry);
28545+ err = ssz;
a2654f78 28546+ if (ssz >= 0) {
c1595e42 28547+ err = 0;
a2654f78
AM
28548+ set_cached_acl(inode, type, acl);
28549+ }
c1595e42
JR
28550+
28551+out:
c1595e42
JR
28552+ return err;
28553+}
7f207e10 28554diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
eca34b5c
AM
28555--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
28556+++ linux/fs/aufs/procfs.c 2019-07-11 15:42:14.472238057 +0200
062440b3 28557@@ -0,0 +1,171 @@
cd7a4cd9 28558+// SPDX-License-Identifier: GPL-2.0
e49829fe 28559+/*
ba1aed25 28560+ * Copyright (C) 2010-2019 Junjiro R. Okajima
e49829fe
JR
28561+ *
28562+ * This program, aufs is free software; you can redistribute it and/or modify
28563+ * it under the terms of the GNU General Public License as published by
28564+ * the Free Software Foundation; either version 2 of the License, or
28565+ * (at your option) any later version.
28566+ *
28567+ * This program is distributed in the hope that it will be useful,
28568+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28569+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28570+ * GNU General Public License for more details.
28571+ *
28572+ * You should have received a copy of the GNU General Public License
523b37e3 28573+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
28574+ */
28575+
28576+/*
28577+ * procfs interfaces
28578+ */
28579+
28580+#include <linux/proc_fs.h>
28581+#include "aufs.h"
28582+
28583+static int au_procfs_plm_release(struct inode *inode, struct file *file)
28584+{
28585+ struct au_sbinfo *sbinfo;
28586+
28587+ sbinfo = file->private_data;
28588+ if (sbinfo) {
28589+ au_plink_maint_leave(sbinfo);
28590+ kobject_put(&sbinfo->si_kobj);
28591+ }
28592+
28593+ return 0;
28594+}
28595+
28596+static void au_procfs_plm_write_clean(struct file *file)
28597+{
28598+ struct au_sbinfo *sbinfo;
28599+
28600+ sbinfo = file->private_data;
28601+ if (sbinfo)
28602+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
28603+}
28604+
28605+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
28606+{
28607+ int err;
28608+ struct super_block *sb;
28609+ struct au_sbinfo *sbinfo;
8b6a4947 28610+ struct hlist_bl_node *pos;
e49829fe
JR
28611+
28612+ err = -EBUSY;
28613+ if (unlikely(file->private_data))
28614+ goto out;
28615+
28616+ sb = NULL;
53392da6 28617+ /* don't use au_sbilist_lock() here */
8b6a4947
AM
28618+ hlist_bl_lock(&au_sbilist);
28619+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
e49829fe 28620+ if (id == sysaufs_si_id(sbinfo)) {
83b672a5
AM
28621+ if (kobject_get_unless_zero(&sbinfo->si_kobj))
28622+ sb = sbinfo->si_sb;
e49829fe
JR
28623+ break;
28624+ }
8b6a4947 28625+ hlist_bl_unlock(&au_sbilist);
e49829fe
JR
28626+
28627+ err = -EINVAL;
28628+ if (unlikely(!sb))
28629+ goto out;
28630+
28631+ err = au_plink_maint_enter(sb);
28632+ if (!err)
28633+ /* keep kobject_get() */
28634+ file->private_data = sbinfo;
28635+ else
28636+ kobject_put(&sbinfo->si_kobj);
28637+out:
28638+ return err;
28639+}
28640+
28641+/*
28642+ * Accept a valid "si=xxxx" only.
28643+ * Once it is accepted successfully, accept "clean" too.
28644+ */
28645+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
28646+ size_t count, loff_t *ppos)
28647+{
28648+ ssize_t err;
28649+ unsigned long id;
28650+ /* last newline is allowed */
28651+ char buf[3 + sizeof(unsigned long) * 2 + 1];
28652+
28653+ err = -EACCES;
28654+ if (unlikely(!capable(CAP_SYS_ADMIN)))
28655+ goto out;
28656+
28657+ err = -EINVAL;
28658+ if (unlikely(count > sizeof(buf)))
28659+ goto out;
28660+
28661+ err = copy_from_user(buf, ubuf, count);
28662+ if (unlikely(err)) {
28663+ err = -EFAULT;
28664+ goto out;
28665+ }
28666+ buf[count] = 0;
28667+
28668+ err = -EINVAL;
28669+ if (!strcmp("clean", buf)) {
28670+ au_procfs_plm_write_clean(file);
28671+ goto out_success;
28672+ } else if (unlikely(strncmp("si=", buf, 3)))
28673+ goto out;
28674+
9dbd164d 28675+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
28676+ if (unlikely(err))
28677+ goto out;
28678+
28679+ err = au_procfs_plm_write_si(file, id);
28680+ if (unlikely(err))
28681+ goto out;
28682+
28683+out_success:
28684+ err = count; /* success */
28685+out:
28686+ return err;
28687+}
28688+
28689+static const struct file_operations au_procfs_plm_fop = {
28690+ .write = au_procfs_plm_write,
28691+ .release = au_procfs_plm_release,
28692+ .owner = THIS_MODULE
28693+};
28694+
28695+/* ---------------------------------------------------------------------- */
28696+
28697+static struct proc_dir_entry *au_procfs_dir;
28698+
28699+void au_procfs_fin(void)
28700+{
28701+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
28702+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28703+}
28704+
28705+int __init au_procfs_init(void)
28706+{
28707+ int err;
28708+ struct proc_dir_entry *entry;
28709+
28710+ err = -ENOMEM;
28711+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
28712+ if (unlikely(!au_procfs_dir))
28713+ goto out;
28714+
cd7a4cd9 28715+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200,
e49829fe
JR
28716+ au_procfs_dir, &au_procfs_plm_fop);
28717+ if (unlikely(!entry))
28718+ goto out_dir;
28719+
28720+ err = 0;
28721+ goto out; /* success */
28722+
28723+
28724+out_dir:
28725+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28726+out:
28727+ return err;
28728+}
7f207e10 28729diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
eca34b5c
AM
28730--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
28731+++ linux/fs/aufs/rdu.c 2019-07-11 15:42:14.472238057 +0200
ba1aed25 28732@@ -0,0 +1,384 @@
cd7a4cd9 28733+// SPDX-License-Identifier: GPL-2.0
1308ab2a 28734+/*
ba1aed25 28735+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1308ab2a 28736+ *
28737+ * This program, aufs is free software; you can redistribute it and/or modify
28738+ * it under the terms of the GNU General Public License as published by
28739+ * the Free Software Foundation; either version 2 of the License, or
28740+ * (at your option) any later version.
28741+ *
28742+ * This program is distributed in the hope that it will be useful,
28743+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28744+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28745+ * GNU General Public License for more details.
28746+ *
28747+ * You should have received a copy of the GNU General Public License
523b37e3 28748+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1308ab2a 28749+ */
28750+
28751+/*
28752+ * readdir in userspace.
28753+ */
28754+
b752ccd1 28755+#include <linux/compat.h>
4a4d8108 28756+#include <linux/fs_stack.h>
1308ab2a 28757+#include <linux/security.h>
1308ab2a 28758+#include "aufs.h"
28759+
28760+/* bits for struct aufs_rdu.flags */
28761+#define AuRdu_CALLED 1
28762+#define AuRdu_CONT (1 << 1)
28763+#define AuRdu_FULL (1 << 2)
28764+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
28765+#define au_fset_rdu(flags, name) \
28766+ do { (flags) |= AuRdu_##name; } while (0)
28767+#define au_fclr_rdu(flags, name) \
28768+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 28769+
28770+struct au_rdu_arg {
392086de 28771+ struct dir_context ctx;
1308ab2a 28772+ struct aufs_rdu *rdu;
28773+ union au_rdu_ent_ul ent;
28774+ unsigned long end;
28775+
28776+ struct super_block *sb;
28777+ int err;
28778+};
28779+
392086de 28780+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen,
1308ab2a 28781+ loff_t offset, u64 h_ino, unsigned int d_type)
28782+{
28783+ int err, len;
392086de 28784+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx);
1308ab2a 28785+ struct aufs_rdu *rdu = arg->rdu;
28786+ struct au_rdu_ent ent;
28787+
28788+ err = 0;
28789+ arg->err = 0;
28790+ au_fset_rdu(rdu->cookie.flags, CALLED);
28791+ len = au_rdu_len(nlen);
28792+ if (arg->ent.ul + len < arg->end) {
28793+ ent.ino = h_ino;
28794+ ent.bindex = rdu->cookie.bindex;
28795+ ent.type = d_type;
28796+ ent.nlen = nlen;
4a4d8108
AM
28797+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
28798+ ent.type = DT_UNKNOWN;
1308ab2a 28799+
9dbd164d 28800+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28801+ err = -EFAULT;
28802+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
28803+ goto out;
28804+ if (copy_to_user(arg->ent.e->name, name, nlen))
28805+ goto out;
28806+ /* the terminating NULL */
28807+ if (__put_user(0, arg->ent.e->name + nlen))
28808+ goto out;
28809+ err = 0;
28810+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
28811+ arg->ent.ul += len;
28812+ rdu->rent++;
28813+ } else {
28814+ err = -EFAULT;
28815+ au_fset_rdu(rdu->cookie.flags, FULL);
28816+ rdu->full = 1;
28817+ rdu->tail = arg->ent;
28818+ }
28819+
4f0767ce 28820+out:
1308ab2a 28821+ /* AuTraceErr(err); */
28822+ return err;
28823+}
28824+
28825+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
28826+{
28827+ int err;
28828+ loff_t offset;
28829+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
28830+
92d182d2 28831+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 28832+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
28833+ err = offset;
28834+ if (unlikely(offset != cookie->h_pos))
28835+ goto out;
28836+
28837+ err = 0;
28838+ do {
28839+ arg->err = 0;
28840+ au_fclr_rdu(cookie->flags, CALLED);
28841+ /* smp_mb(); */
392086de 28842+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1308ab2a 28843+ if (err >= 0)
28844+ err = arg->err;
28845+ } while (!err
28846+ && au_ftest_rdu(cookie->flags, CALLED)
28847+ && !au_ftest_rdu(cookie->flags, FULL));
28848+ cookie->h_pos = h_file->f_pos;
28849+
4f0767ce 28850+out:
1308ab2a 28851+ AuTraceErr(err);
28852+ return err;
28853+}
28854+
28855+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
28856+{
28857+ int err;
5afbbe0d 28858+ aufs_bindex_t bbot;
392086de
AM
28859+ struct au_rdu_arg arg = {
28860+ .ctx = {
2000de60 28861+ .actor = au_rdu_fill
392086de
AM
28862+ }
28863+ };
1308ab2a 28864+ struct dentry *dentry;
28865+ struct inode *inode;
28866+ struct file *h_file;
28867+ struct au_rdu_cookie *cookie = &rdu->cookie;
28868+
ba1aed25
AM
28869+ /* VERIFY_WRITE */
28870+ err = !access_ok(rdu->ent.e, rdu->sz);
1308ab2a 28871+ if (unlikely(err)) {
28872+ err = -EFAULT;
28873+ AuTraceErr(err);
28874+ goto out;
28875+ }
28876+ rdu->rent = 0;
28877+ rdu->tail = rdu->ent;
28878+ rdu->full = 0;
28879+ arg.rdu = rdu;
28880+ arg.ent = rdu->ent;
28881+ arg.end = arg.ent.ul;
28882+ arg.end += rdu->sz;
28883+
28884+ err = -ENOTDIR;
5afbbe0d 28885+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared))
1308ab2a 28886+ goto out;
28887+
28888+ err = security_file_permission(file, MAY_READ);
28889+ AuTraceErr(err);
28890+ if (unlikely(err))
28891+ goto out;
28892+
2000de60 28893+ dentry = file->f_path.dentry;
5527c038 28894+ inode = d_inode(dentry);
5afbbe0d 28895+ inode_lock_shared(inode);
1308ab2a 28896+
28897+ arg.sb = inode->i_sb;
e49829fe
JR
28898+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
28899+ if (unlikely(err))
28900+ goto out_mtx;
027c5e7a
AM
28901+ err = au_alive_dir(dentry);
28902+ if (unlikely(err))
28903+ goto out_si;
e49829fe 28904+ /* todo: reval? */
1308ab2a 28905+ fi_read_lock(file);
28906+
28907+ err = -EAGAIN;
28908+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
28909+ && cookie->generation != au_figen(file)))
28910+ goto out_unlock;
28911+
28912+ err = 0;
28913+ if (!rdu->blk) {
28914+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
28915+ if (!rdu->blk)
28916+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
28917+ }
5afbbe0d
AM
28918+ bbot = au_fbtop(file);
28919+ if (cookie->bindex < bbot)
28920+ cookie->bindex = bbot;
28921+ bbot = au_fbbot_dir(file);
28922+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */
28923+ for (; !err && cookie->bindex <= bbot;
1308ab2a 28924+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 28925+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 28926+ if (!h_file)
28927+ continue;
28928+
28929+ au_fclr_rdu(cookie->flags, FULL);
28930+ err = au_rdu_do(h_file, &arg);
28931+ AuTraceErr(err);
28932+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
28933+ break;
28934+ }
28935+ AuDbg("rent %llu\n", rdu->rent);
28936+
28937+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
28938+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
28939+ au_fset_rdu(cookie->flags, CONT);
28940+ cookie->generation = au_figen(file);
28941+ }
28942+
28943+ ii_read_lock_child(inode);
5afbbe0d 28944+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode)));
1308ab2a 28945+ ii_read_unlock(inode);
28946+
4f0767ce 28947+out_unlock:
1308ab2a 28948+ fi_read_unlock(file);
027c5e7a 28949+out_si:
1308ab2a 28950+ si_read_unlock(arg.sb);
4f0767ce 28951+out_mtx:
5afbbe0d 28952+ inode_unlock_shared(inode);
4f0767ce 28953+out:
1308ab2a 28954+ AuTraceErr(err);
28955+ return err;
28956+}
28957+
28958+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
28959+{
28960+ int err;
28961+ ino_t ino;
28962+ unsigned long long nent;
28963+ union au_rdu_ent_ul *u;
28964+ struct au_rdu_ent ent;
28965+ struct super_block *sb;
28966+
28967+ err = 0;
28968+ nent = rdu->nent;
28969+ u = &rdu->ent;
2000de60 28970+ sb = file->f_path.dentry->d_sb;
1308ab2a 28971+ si_read_lock(sb, AuLock_FLUSH);
28972+ while (nent-- > 0) {
9dbd164d 28973+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28974+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108 28975+ if (!err)
ba1aed25
AM
28976+ /* VERIFY_WRITE */
28977+ err = !access_ok(&u->e->ino, sizeof(ino));
1308ab2a 28978+ if (unlikely(err)) {
28979+ err = -EFAULT;
28980+ AuTraceErr(err);
28981+ break;
28982+ }
28983+
28984+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
28985+ if (!ent.wh)
28986+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
28987+ else
28988+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
28989+ &ino);
28990+ if (unlikely(err)) {
28991+ AuTraceErr(err);
28992+ break;
28993+ }
28994+
28995+ err = __put_user(ino, &u->e->ino);
28996+ if (unlikely(err)) {
28997+ err = -EFAULT;
28998+ AuTraceErr(err);
28999+ break;
29000+ }
29001+ u->ul += au_rdu_len(ent.nlen);
29002+ }
29003+ si_read_unlock(sb);
29004+
29005+ return err;
29006+}
29007+
29008+/* ---------------------------------------------------------------------- */
29009+
29010+static int au_rdu_verify(struct aufs_rdu *rdu)
29011+{
b752ccd1 29012+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 29013+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 29014+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 29015+ rdu->blk,
29016+ rdu->rent, rdu->shwh, rdu->full,
29017+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
29018+ rdu->cookie.generation);
dece6358 29019+
b752ccd1 29020+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 29021+ return 0;
dece6358 29022+
b752ccd1
AM
29023+ AuDbg("%u:%u\n",
29024+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 29025+ return -EINVAL;
29026+}
29027+
29028+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 29029+{
1308ab2a 29030+ long err, e;
29031+ struct aufs_rdu rdu;
29032+ void __user *p = (void __user *)arg;
dece6358 29033+
1308ab2a 29034+ err = copy_from_user(&rdu, p, sizeof(rdu));
29035+ if (unlikely(err)) {
29036+ err = -EFAULT;
29037+ AuTraceErr(err);
29038+ goto out;
29039+ }
29040+ err = au_rdu_verify(&rdu);
dece6358
AM
29041+ if (unlikely(err))
29042+ goto out;
29043+
1308ab2a 29044+ switch (cmd) {
29045+ case AUFS_CTL_RDU:
29046+ err = au_rdu(file, &rdu);
29047+ if (unlikely(err))
29048+ break;
dece6358 29049+
1308ab2a 29050+ e = copy_to_user(p, &rdu, sizeof(rdu));
29051+ if (unlikely(e)) {
29052+ err = -EFAULT;
29053+ AuTraceErr(err);
29054+ }
29055+ break;
29056+ case AUFS_CTL_RDU_INO:
29057+ err = au_rdu_ino(file, &rdu);
29058+ break;
29059+
29060+ default:
4a4d8108 29061+ /* err = -ENOTTY; */
1308ab2a 29062+ err = -EINVAL;
29063+ }
dece6358 29064+
4f0767ce 29065+out:
1308ab2a 29066+ AuTraceErr(err);
29067+ return err;
1facf9fc 29068+}
b752ccd1
AM
29069+
29070+#ifdef CONFIG_COMPAT
29071+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
29072+{
29073+ long err, e;
29074+ struct aufs_rdu rdu;
29075+ void __user *p = compat_ptr(arg);
29076+
29077+ /* todo: get_user()? */
29078+ err = copy_from_user(&rdu, p, sizeof(rdu));
29079+ if (unlikely(err)) {
29080+ err = -EFAULT;
29081+ AuTraceErr(err);
29082+ goto out;
29083+ }
29084+ rdu.ent.e = compat_ptr(rdu.ent.ul);
29085+ err = au_rdu_verify(&rdu);
29086+ if (unlikely(err))
29087+ goto out;
29088+
29089+ switch (cmd) {
29090+ case AUFS_CTL_RDU:
29091+ err = au_rdu(file, &rdu);
29092+ if (unlikely(err))
29093+ break;
29094+
29095+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
29096+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
29097+ e = copy_to_user(p, &rdu, sizeof(rdu));
29098+ if (unlikely(e)) {
29099+ err = -EFAULT;
29100+ AuTraceErr(err);
29101+ }
29102+ break;
29103+ case AUFS_CTL_RDU_INO:
29104+ err = au_rdu_ino(file, &rdu);
29105+ break;
29106+
29107+ default:
29108+ /* err = -ENOTTY; */
29109+ err = -EINVAL;
29110+ }
29111+
4f0767ce 29112+out:
b752ccd1
AM
29113+ AuTraceErr(err);
29114+ return err;
29115+}
29116+#endif
7f207e10 29117diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
eca34b5c
AM
29118--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
29119+++ linux/fs/aufs/rwsem.h 2019-07-11 15:42:14.472238057 +0200
062440b3
AM
29120@@ -0,0 +1,73 @@
29121+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 29122+/*
ba1aed25 29123+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 29124+ *
29125+ * This program, aufs is free software; you can redistribute it and/or modify
29126+ * it under the terms of the GNU General Public License as published by
29127+ * the Free Software Foundation; either version 2 of the License, or
29128+ * (at your option) any later version.
dece6358
AM
29129+ *
29130+ * This program is distributed in the hope that it will be useful,
29131+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29132+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29133+ * GNU General Public License for more details.
29134+ *
29135+ * You should have received a copy of the GNU General Public License
523b37e3 29136+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29137+ */
29138+
29139+/*
29140+ * simple read-write semaphore wrappers
29141+ */
29142+
29143+#ifndef __AUFS_RWSEM_H__
29144+#define __AUFS_RWSEM_H__
29145+
29146+#ifdef __KERNEL__
29147+
4a4d8108 29148+#include "debug.h"
dece6358 29149+
acd2b654 29150+/* in the future, the name 'au_rwsem' will be totally gone */
8b6a4947 29151+#define au_rwsem rw_semaphore
dece6358
AM
29152+
29153+/* to debug easier, do not make them inlined functions */
8b6a4947 29154+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw))
dece6358 29155+/* rwsem_is_locked() is unusable */
8b6a4947
AM
29156+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \
29157+ && debug_locks \
29158+ && !lockdep_is_held_type(rw, 1))
29159+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \
29160+ && debug_locks \
29161+ && !lockdep_is_held_type(rw, 0))
29162+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \
29163+ && debug_locks \
29164+ && !lockdep_is_held(rw))
29165+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \
29166+ && debug_locks \
29167+ && lockdep_is_held(rw))
29168+
29169+#define au_rw_init(rw) init_rwsem(rw)
dece6358 29170+
5afbbe0d
AM
29171+#define au_rw_init_wlock(rw) do { \
29172+ au_rw_init(rw); \
8b6a4947 29173+ down_write(rw); \
5afbbe0d 29174+ } while (0)
dece6358 29175+
8b6a4947
AM
29176+#define au_rw_init_wlock_nested(rw, lsc) do { \
29177+ au_rw_init(rw); \
29178+ down_write_nested(rw, lsc); \
5afbbe0d 29179+ } while (0)
dece6358 29180+
8b6a4947
AM
29181+#define au_rw_read_lock(rw) down_read(rw)
29182+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc)
29183+#define au_rw_read_unlock(rw) up_read(rw)
29184+#define au_rw_dgrade_lock(rw) downgrade_write(rw)
29185+#define au_rw_write_lock(rw) down_write(rw)
29186+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc)
29187+#define au_rw_write_unlock(rw) up_write(rw)
29188+/* why is not _nested version defined? */
29189+#define au_rw_read_trylock(rw) down_read_trylock(rw)
29190+#define au_rw_write_trylock(rw) down_write_trylock(rw)
1facf9fc 29191+
29192+#endif /* __KERNEL__ */
29193+#endif /* __AUFS_RWSEM_H__ */
7f207e10 29194diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
eca34b5c
AM
29195--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
29196+++ linux/fs/aufs/sbinfo.c 2019-07-11 15:42:14.472238057 +0200
eca801bf 29197@@ -0,0 +1,314 @@
cd7a4cd9 29198+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29199+/*
ba1aed25 29200+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 29201+ *
29202+ * This program, aufs is free software; you can redistribute it and/or modify
29203+ * it under the terms of the GNU General Public License as published by
29204+ * the Free Software Foundation; either version 2 of the License, or
29205+ * (at your option) any later version.
dece6358
AM
29206+ *
29207+ * This program is distributed in the hope that it will be useful,
29208+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29209+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29210+ * GNU General Public License for more details.
29211+ *
29212+ * You should have received a copy of the GNU General Public License
523b37e3 29213+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29214+ */
29215+
29216+/*
29217+ * superblock private data
29218+ */
29219+
eca801bf 29220+#include <linux/iversion.h>
1facf9fc 29221+#include "aufs.h"
29222+
29223+/*
29224+ * they are necessary regardless sysfs is disabled.
29225+ */
29226+void au_si_free(struct kobject *kobj)
29227+{
86dc4139 29228+ int i;
1facf9fc 29229+ struct au_sbinfo *sbinfo;
b752ccd1 29230+ char *locked __maybe_unused; /* debug only */
1facf9fc 29231+
29232+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
86dc4139 29233+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29234+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i));
f0c0a007 29235+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
5afbbe0d 29236+
acd2b654
AM
29237+ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0));
29238+ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0);
29239+ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0));
29240+ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0);
1facf9fc 29241+
062440b3 29242+ dbgaufs_si_fin(sbinfo);
e49829fe 29243+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 29244+ au_br_free(sbinfo);
e49829fe 29245+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1 29246+
9f237c51 29247+ au_kfree_try_rcu(sbinfo->si_branch);
1facf9fc 29248+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 29249+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 29250+
acd2b654
AM
29251+ au_lcnt_wait_for_fin(&sbinfo->si_ninodes);
29252+ /* si_nfiles is waited too */
9f237c51 29253+ au_kfree_rcu(sbinfo);
1facf9fc 29254+}
29255+
29256+int au_si_alloc(struct super_block *sb)
29257+{
86dc4139 29258+ int err, i;
1facf9fc 29259+ struct au_sbinfo *sbinfo;
29260+
29261+ err = -ENOMEM;
4a4d8108 29262+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 29263+ if (unlikely(!sbinfo))
29264+ goto out;
29265+
29266+ /* will be reallocated separately */
29267+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
29268+ if (unlikely(!sbinfo->si_branch))
febd17d6 29269+ goto out_sbinfo;
1facf9fc 29270+
1facf9fc 29271+ err = sysaufs_si_init(sbinfo);
062440b3
AM
29272+ if (!err) {
29273+ dbgaufs_si_null(sbinfo);
29274+ err = dbgaufs_si_init(sbinfo);
29275+ if (unlikely(err))
29276+ kobject_put(&sbinfo->si_kobj);
29277+ }
1facf9fc 29278+ if (unlikely(err))
29279+ goto out_br;
29280+
29281+ au_nwt_init(&sbinfo->si_nowait);
dece6358 29282+ au_rw_init_wlock(&sbinfo->si_rwsem);
b752ccd1 29283+
acd2b654
AM
29284+ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL);
29285+ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL);
7f207e10 29286+
5afbbe0d 29287+ sbinfo->si_bbot = -1;
392086de 29288+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2;
1facf9fc 29289+
29290+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
29291+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
29292+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
29293+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 29294+
076b876e
AM
29295+ au_fhsm_init(sbinfo);
29296+
e49829fe 29297+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 29298+
392086de
AM
29299+ sbinfo->si_xino_jiffy = jiffies;
29300+ sbinfo->si_xino_expire
29301+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC);
1facf9fc 29302+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 29303+ /* leave si_xib_last_pindex and si_xib_next_bit */
29304+
8b6a4947 29305+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen);
b912730e 29306+
e49829fe 29307+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 29308+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
29309+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
29310+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
29311+
86dc4139 29312+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29313+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i);
1facf9fc 29314+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 29315+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 29316+
8b6a4947 29317+ INIT_HLIST_BL_HEAD(&sbinfo->si_files);
523b37e3 29318+
b95c5147
AM
29319+ /* with getattr by default */
29320+ sbinfo->si_iop_array = aufs_iop;
29321+
1facf9fc 29322+ /* leave other members for sysaufs and si_mnt. */
29323+ sbinfo->si_sb = sb;
29324+ sb->s_fs_info = sbinfo;
b752ccd1 29325+ si_pid_set(sb);
1facf9fc 29326+ return 0; /* success */
29327+
4f0767ce 29328+out_br:
9f237c51 29329+ au_kfree_try_rcu(sbinfo->si_branch);
4f0767ce 29330+out_sbinfo:
9f237c51 29331+ au_kfree_rcu(sbinfo);
4f0767ce 29332+out:
1facf9fc 29333+ return err;
29334+}
29335+
e2f27e51 29336+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
1facf9fc 29337+{
29338+ int err, sz;
29339+ struct au_branch **brp;
29340+
dece6358
AM
29341+ AuRwMustWriteLock(&sbinfo->si_rwsem);
29342+
1facf9fc 29343+ err = -ENOMEM;
5afbbe0d 29344+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1);
1facf9fc 29345+ if (unlikely(!sz))
29346+ sz = sizeof(*brp);
e2f27e51
AM
29347+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS,
29348+ may_shrink);
1facf9fc 29349+ if (brp) {
29350+ sbinfo->si_branch = brp;
29351+ err = 0;
29352+ }
29353+
29354+ return err;
29355+}
29356+
29357+/* ---------------------------------------------------------------------- */
29358+
29359+unsigned int au_sigen_inc(struct super_block *sb)
29360+{
29361+ unsigned int gen;
5527c038 29362+ struct inode *inode;
1facf9fc 29363+
dece6358
AM
29364+ SiMustWriteLock(sb);
29365+
1facf9fc 29366+ gen = ++au_sbi(sb)->si_generation;
29367+ au_update_digen(sb->s_root);
5527c038
JR
29368+ inode = d_inode(sb->s_root);
29369+ au_update_iigen(inode, /*half*/0);
be118d29 29370+ inode_inc_iversion(inode);
1facf9fc 29371+ return gen;
29372+}
29373+
29374+aufs_bindex_t au_new_br_id(struct super_block *sb)
29375+{
29376+ aufs_bindex_t br_id;
29377+ int i;
29378+ struct au_sbinfo *sbinfo;
29379+
dece6358
AM
29380+ SiMustWriteLock(sb);
29381+
1facf9fc 29382+ sbinfo = au_sbi(sb);
29383+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
29384+ br_id = ++sbinfo->si_last_br_id;
7f207e10 29385+ AuDebugOn(br_id < 0);
1facf9fc 29386+ if (br_id && au_br_index(sb, br_id) < 0)
29387+ return br_id;
29388+ }
29389+
29390+ return -1;
29391+}
29392+
29393+/* ---------------------------------------------------------------------- */
29394+
e49829fe
JR
29395+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
29396+int si_read_lock(struct super_block *sb, int flags)
29397+{
29398+ int err;
29399+
29400+ err = 0;
29401+ if (au_ftest_lock(flags, FLUSH))
29402+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29403+
29404+ si_noflush_read_lock(sb);
29405+ err = au_plink_maint(sb, flags);
29406+ if (unlikely(err))
29407+ si_read_unlock(sb);
29408+
29409+ return err;
29410+}
29411+
29412+int si_write_lock(struct super_block *sb, int flags)
29413+{
29414+ int err;
29415+
29416+ if (au_ftest_lock(flags, FLUSH))
29417+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29418+
29419+ si_noflush_write_lock(sb);
29420+ err = au_plink_maint(sb, flags);
29421+ if (unlikely(err))
29422+ si_write_unlock(sb);
29423+
29424+ return err;
29425+}
29426+
1facf9fc 29427+/* dentry and super_block lock. call at entry point */
e49829fe 29428+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 29429+{
e49829fe 29430+ int err;
027c5e7a 29431+ struct super_block *sb;
e49829fe 29432+
027c5e7a
AM
29433+ sb = dentry->d_sb;
29434+ err = si_read_lock(sb, flags);
29435+ if (unlikely(err))
29436+ goto out;
29437+
29438+ if (au_ftest_lock(flags, DW))
29439+ di_write_lock_child(dentry);
29440+ else
29441+ di_read_lock_child(dentry, flags);
29442+
29443+ if (au_ftest_lock(flags, GEN)) {
29444+ err = au_digen_test(dentry, au_sigen(sb));
79b8bda9
AM
29445+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE))
29446+ AuDebugOn(!err && au_dbrange_test(dentry));
29447+ else if (!err)
29448+ err = au_dbrange_test(dentry);
027c5e7a
AM
29449+ if (unlikely(err))
29450+ aufs_read_unlock(dentry, flags);
e49829fe
JR
29451+ }
29452+
027c5e7a 29453+out:
e49829fe 29454+ return err;
1facf9fc 29455+}
29456+
29457+void aufs_read_unlock(struct dentry *dentry, int flags)
29458+{
29459+ if (au_ftest_lock(flags, DW))
29460+ di_write_unlock(dentry);
29461+ else
29462+ di_read_unlock(dentry, flags);
29463+ si_read_unlock(dentry->d_sb);
29464+}
29465+
29466+void aufs_write_lock(struct dentry *dentry)
29467+{
e49829fe 29468+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 29469+ di_write_lock_child(dentry);
29470+}
29471+
29472+void aufs_write_unlock(struct dentry *dentry)
29473+{
29474+ di_write_unlock(dentry);
29475+ si_write_unlock(dentry->d_sb);
29476+}
29477+
e49829fe 29478+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 29479+{
e49829fe 29480+ int err;
027c5e7a
AM
29481+ unsigned int sigen;
29482+ struct super_block *sb;
e49829fe 29483+
027c5e7a
AM
29484+ sb = d1->d_sb;
29485+ err = si_read_lock(sb, flags);
29486+ if (unlikely(err))
29487+ goto out;
29488+
b95c5147 29489+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS));
027c5e7a
AM
29490+
29491+ if (au_ftest_lock(flags, GEN)) {
29492+ sigen = au_sigen(sb);
29493+ err = au_digen_test(d1, sigen);
29494+ AuDebugOn(!err && au_dbrange_test(d1));
29495+ if (!err) {
29496+ err = au_digen_test(d2, sigen);
29497+ AuDebugOn(!err && au_dbrange_test(d2));
29498+ }
29499+ if (unlikely(err))
29500+ aufs_read_and_write_unlock2(d1, d2);
29501+ }
29502+
29503+out:
e49829fe 29504+ return err;
1facf9fc 29505+}
29506+
29507+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
29508+{
29509+ di_write_unlock2(d1, d2);
29510+ si_read_unlock(d1->d_sb);
29511+}
7f207e10 29512diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
eca34b5c
AM
29513--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
29514+++ linux/fs/aufs/super.c 2019-07-11 15:42:14.472238057 +0200
fbc438ed 29515@@ -0,0 +1,1047 @@
cd7a4cd9 29516+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29517+/*
ba1aed25 29518+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 29519+ *
29520+ * This program, aufs is free software; you can redistribute it and/or modify
29521+ * it under the terms of the GNU General Public License as published by
29522+ * the Free Software Foundation; either version 2 of the License, or
29523+ * (at your option) any later version.
dece6358
AM
29524+ *
29525+ * This program is distributed in the hope that it will be useful,
29526+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29527+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29528+ * GNU General Public License for more details.
29529+ *
29530+ * You should have received a copy of the GNU General Public License
523b37e3 29531+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29532+ */
29533+
29534+/*
29535+ * mount and super_block operations
29536+ */
29537+
eca801bf 29538+#include <linux/iversion.h>
f6c5ef8b 29539+#include <linux/mm.h>
1facf9fc 29540+#include <linux/seq_file.h>
29541+#include <linux/statfs.h>
7f207e10 29542+#include <linux/vmalloc.h>
1facf9fc 29543+#include "aufs.h"
29544+
29545+/*
29546+ * super_operations
29547+ */
29548+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
29549+{
29550+ struct au_icntnr *c;
29551+
29552+ c = au_cache_alloc_icntnr();
29553+ if (c) {
027c5e7a 29554+ au_icntnr_init(c);
be118d29 29555+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */
1facf9fc 29556+ c->iinfo.ii_hinode = NULL;
29557+ return &c->vfs_inode;
29558+ }
29559+ return NULL;
29560+}
29561+
29562+static void aufs_destroy_inode(struct inode *inode)
29563+{
5afbbe0d
AM
29564+ if (!au_is_bad_inode(inode))
29565+ au_iinfo_fin(inode);
fbc438ed
JR
29566+}
29567+
29568+static void aufs_free_inode(struct inode *inode)
29569+{
29570+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
1facf9fc 29571+}
29572+
29573+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
29574+{
29575+ struct inode *inode;
29576+ int err;
29577+
29578+ inode = iget_locked(sb, ino);
29579+ if (unlikely(!inode)) {
29580+ inode = ERR_PTR(-ENOMEM);
29581+ goto out;
29582+ }
29583+ if (!(inode->i_state & I_NEW))
29584+ goto out;
29585+
29586+ err = au_xigen_new(inode);
29587+ if (!err)
29588+ err = au_iinfo_init(inode);
29589+ if (!err)
be118d29 29590+ inode_inc_iversion(inode);
1facf9fc 29591+ else {
29592+ iget_failed(inode);
29593+ inode = ERR_PTR(err);
29594+ }
29595+
4f0767ce 29596+out:
1facf9fc 29597+ /* never return NULL */
29598+ AuDebugOn(!inode);
29599+ AuTraceErrPtr(inode);
29600+ return inode;
29601+}
29602+
29603+/* lock free root dinfo */
29604+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
29605+{
29606+ int err;
5afbbe0d 29607+ aufs_bindex_t bindex, bbot;
1facf9fc 29608+ struct path path;
4a4d8108 29609+ struct au_hdentry *hdp;
1facf9fc 29610+ struct au_branch *br;
076b876e 29611+ au_br_perm_str_t perm;
1facf9fc 29612+
29613+ err = 0;
5afbbe0d
AM
29614+ bbot = au_sbbot(sb);
29615+ bindex = 0;
29616+ hdp = au_hdentry(au_di(sb->s_root), bindex);
29617+ for (; !err && bindex <= bbot; bindex++, hdp++) {
1facf9fc 29618+ br = au_sbr(sb, bindex);
86dc4139 29619+ path.mnt = au_br_mnt(br);
5afbbe0d 29620+ path.dentry = hdp->hd_dentry;
1facf9fc 29621+ err = au_seq_path(seq, &path);
79b8bda9 29622+ if (!err) {
076b876e 29623+ au_optstr_br_perm(&perm, br->br_perm);
79b8bda9 29624+ seq_printf(seq, "=%s", perm.a);
5afbbe0d 29625+ if (bindex != bbot)
79b8bda9 29626+ seq_putc(seq, ':');
1e00d052 29627+ }
1facf9fc 29628+ }
79b8bda9
AM
29629+ if (unlikely(err || seq_has_overflowed(seq)))
29630+ err = -E2BIG;
1facf9fc 29631+
29632+ return err;
29633+}
29634+
f2c43d5f
AM
29635+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat,
29636+ const char *append)
29637+{
29638+ char *p;
29639+
29640+ p = fmt;
29641+ while (*pat != ':')
29642+ *p++ = *pat++;
29643+ *p++ = *pat++;
29644+ strcpy(p, append);
29645+ AuDebugOn(strlen(fmt) >= len);
29646+}
29647+
1facf9fc 29648+static void au_show_wbr_create(struct seq_file *m, int v,
29649+ struct au_sbinfo *sbinfo)
29650+{
29651+ const char *pat;
f2c43d5f
AM
29652+ char fmt[32];
29653+ struct au_wbr_mfs *mfs;
1facf9fc 29654+
dece6358
AM
29655+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29656+
c2b27bf2 29657+ seq_puts(m, ",create=");
1facf9fc 29658+ pat = au_optstr_wbr_create(v);
f2c43d5f 29659+ mfs = &sbinfo->si_wbr_mfs;
1facf9fc 29660+ switch (v) {
29661+ case AuWbrCreate_TDP:
29662+ case AuWbrCreate_RR:
29663+ case AuWbrCreate_MFS:
29664+ case AuWbrCreate_PMFS:
c2b27bf2 29665+ seq_puts(m, pat);
1facf9fc 29666+ break;
f2c43d5f
AM
29667+ case AuWbrCreate_MFSRR:
29668+ case AuWbrCreate_TDMFS:
29669+ case AuWbrCreate_PMFSRR:
29670+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu");
29671+ seq_printf(m, fmt, mfs->mfsrr_watermark);
1facf9fc 29672+ break;
f2c43d5f 29673+ case AuWbrCreate_MFSV:
1facf9fc 29674+ case AuWbrCreate_PMFSV:
f2c43d5f
AM
29675+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu");
29676+ seq_printf(m, fmt,
29677+ jiffies_to_msecs(mfs->mfs_expire)
e49829fe 29678+ / MSEC_PER_SEC);
1facf9fc 29679+ break;
1facf9fc 29680+ case AuWbrCreate_MFSRRV:
f2c43d5f 29681+ case AuWbrCreate_TDMFSV:
392086de 29682+ case AuWbrCreate_PMFSRRV:
f2c43d5f
AM
29683+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu");
29684+ seq_printf(m, fmt, mfs->mfsrr_watermark,
29685+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC);
392086de 29686+ break;
f2c43d5f
AM
29687+ default:
29688+ BUG();
1facf9fc 29689+ }
29690+}
29691+
7eafdf33 29692+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 29693+{
29694+#ifdef CONFIG_SYSFS
29695+ return 0;
29696+#else
29697+ int err;
29698+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
29699+ aufs_bindex_t bindex, brid;
1facf9fc 29700+ struct qstr *name;
29701+ struct file *f;
29702+ struct dentry *d, *h_root;
acd2b654 29703+ struct au_branch *br;
1facf9fc 29704+
dece6358
AM
29705+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29706+
1facf9fc 29707+ err = 0;
1facf9fc 29708+ f = au_sbi(sb)->si_xib;
29709+ if (!f)
29710+ goto out;
29711+
29712+ /* stop printing the default xino path on the first writable branch */
29713+ h_root = NULL;
acd2b654
AM
29714+ bindex = au_xi_root(sb, f->f_path.dentry);
29715+ if (bindex >= 0) {
29716+ br = au_sbr_sb(sb, bindex);
29717+ h_root = au_br_dentry(br);
1facf9fc 29718+ }
acd2b654 29719+
2000de60 29720+ d = f->f_path.dentry;
1facf9fc 29721+ name = &d->d_name;
29722+ /* safe ->d_parent because the file is unlinked */
29723+ if (d->d_parent == h_root
29724+ && name->len == len
29725+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
29726+ goto out;
29727+
29728+ seq_puts(seq, ",xino=");
29729+ err = au_xino_path(seq, f);
29730+
4f0767ce 29731+out:
1facf9fc 29732+ return err;
29733+#endif
29734+}
29735+
29736+/* seq_file will re-call me in case of too long string */
7eafdf33 29737+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 29738+{
027c5e7a 29739+ int err;
1facf9fc 29740+ unsigned int mnt_flags, v;
29741+ struct super_block *sb;
29742+ struct au_sbinfo *sbinfo;
29743+
29744+#define AuBool(name, str) do { \
29745+ v = au_opt_test(mnt_flags, name); \
29746+ if (v != au_opt_test(AuOpt_Def, name)) \
29747+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
29748+} while (0)
29749+
29750+#define AuStr(name, str) do { \
29751+ v = mnt_flags & AuOptMask_##name; \
29752+ if (v != (AuOpt_Def & AuOptMask_##name)) \
29753+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
29754+} while (0)
29755+
29756+#define AuUInt(name, str, val) do { \
29757+ if (val != AUFS_##name##_DEF) \
29758+ seq_printf(m, "," #str "=%u", val); \
29759+} while (0)
29760+
7eafdf33 29761+ sb = dentry->d_sb;
2121bcd9 29762+ if (sb->s_flags & SB_POSIXACL)
c1595e42 29763+ seq_puts(m, ",acl");
be118d29
JR
29764+#if 0
29765+ if (sb->s_flags & SB_I_VERSION)
29766+ seq_puts(m, ",i_version");
29767+#endif
c1595e42
JR
29768+
29769+ /* lock free root dinfo */
1facf9fc 29770+ si_noflush_read_lock(sb);
29771+ sbinfo = au_sbi(sb);
29772+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
29773+
29774+ mnt_flags = au_mntflags(sb);
29775+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 29776+ err = au_show_xino(m, sb);
1facf9fc 29777+ if (unlikely(err))
29778+ goto out;
29779+ } else
29780+ seq_puts(m, ",noxino");
29781+
29782+ AuBool(TRUNC_XINO, trunc_xino);
29783+ AuStr(UDBA, udba);
dece6358 29784+ AuBool(SHWH, shwh);
1facf9fc 29785+ AuBool(PLINK, plink);
4a4d8108 29786+ AuBool(DIO, dio);
076b876e 29787+ AuBool(DIRPERM1, dirperm1);
1facf9fc 29788+
29789+ v = sbinfo->si_wbr_create;
29790+ if (v != AuWbrCreate_Def)
29791+ au_show_wbr_create(m, v, sbinfo);
29792+
29793+ v = sbinfo->si_wbr_copyup;
29794+ if (v != AuWbrCopyup_Def)
29795+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
29796+
29797+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
29798+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
29799+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
29800+
29801+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
29802+
027c5e7a
AM
29803+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
29804+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 29805+
29806+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
29807+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
29808+
076b876e
AM
29809+ au_fhsm_show(m, sbinfo);
29810+
8b6a4947 29811+ AuBool(DIRREN, dirren);
1facf9fc 29812+ AuBool(SUM, sum);
29813+ /* AuBool(SUM_W, wsum); */
29814+ AuBool(WARN_PERM, warn_perm);
29815+ AuBool(VERBOSE, verbose);
29816+
4f0767ce 29817+out:
1facf9fc 29818+ /* be sure to print "br:" last */
29819+ if (!sysaufs_brs) {
29820+ seq_puts(m, ",br:");
29821+ au_show_brs(m, sb);
29822+ }
29823+ si_read_unlock(sb);
29824+ return 0;
29825+
1facf9fc 29826+#undef AuBool
29827+#undef AuStr
4a4d8108 29828+#undef AuUInt
1facf9fc 29829+}
29830+
29831+/* ---------------------------------------------------------------------- */
29832+
29833+/* sum mode which returns the summation for statfs(2) */
29834+
29835+static u64 au_add_till_max(u64 a, u64 b)
29836+{
29837+ u64 old;
29838+
29839+ old = a;
29840+ a += b;
92d182d2
AM
29841+ if (old <= a)
29842+ return a;
29843+ return ULLONG_MAX;
29844+}
29845+
29846+static u64 au_mul_till_max(u64 a, long mul)
29847+{
29848+ u64 old;
29849+
29850+ old = a;
29851+ a *= mul;
29852+ if (old <= a)
1facf9fc 29853+ return a;
29854+ return ULLONG_MAX;
29855+}
29856+
29857+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
29858+{
29859+ int err;
92d182d2 29860+ long bsize, factor;
1facf9fc 29861+ u64 blocks, bfree, bavail, files, ffree;
5afbbe0d 29862+ aufs_bindex_t bbot, bindex, i;
1facf9fc 29863+ unsigned char shared;
7f207e10 29864+ struct path h_path;
1facf9fc 29865+ struct super_block *h_sb;
29866+
92d182d2
AM
29867+ err = 0;
29868+ bsize = LONG_MAX;
29869+ files = 0;
29870+ ffree = 0;
1facf9fc 29871+ blocks = 0;
29872+ bfree = 0;
29873+ bavail = 0;
5afbbe0d
AM
29874+ bbot = au_sbbot(sb);
29875+ for (bindex = 0; bindex <= bbot; bindex++) {
7f207e10
AM
29876+ h_path.mnt = au_sbr_mnt(sb, bindex);
29877+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 29878+ shared = 0;
92d182d2 29879+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 29880+ shared = (au_sbr_sb(sb, i) == h_sb);
29881+ if (shared)
29882+ continue;
29883+
29884+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29885+ h_path.dentry = h_path.mnt->mnt_root;
29886+ err = vfs_statfs(&h_path, buf);
1facf9fc 29887+ if (unlikely(err))
29888+ goto out;
29889+
92d182d2
AM
29890+ if (bsize > buf->f_bsize) {
29891+ /*
29892+ * we will reduce bsize, so we have to expand blocks
29893+ * etc. to match them again
29894+ */
29895+ factor = (bsize / buf->f_bsize);
29896+ blocks = au_mul_till_max(blocks, factor);
29897+ bfree = au_mul_till_max(bfree, factor);
29898+ bavail = au_mul_till_max(bavail, factor);
29899+ bsize = buf->f_bsize;
29900+ }
29901+
29902+ factor = (buf->f_bsize / bsize);
29903+ blocks = au_add_till_max(blocks,
29904+ au_mul_till_max(buf->f_blocks, factor));
29905+ bfree = au_add_till_max(bfree,
29906+ au_mul_till_max(buf->f_bfree, factor));
29907+ bavail = au_add_till_max(bavail,
29908+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 29909+ files = au_add_till_max(files, buf->f_files);
29910+ ffree = au_add_till_max(ffree, buf->f_ffree);
29911+ }
29912+
92d182d2 29913+ buf->f_bsize = bsize;
1facf9fc 29914+ buf->f_blocks = blocks;
29915+ buf->f_bfree = bfree;
29916+ buf->f_bavail = bavail;
29917+ buf->f_files = files;
29918+ buf->f_ffree = ffree;
92d182d2 29919+ buf->f_frsize = 0;
1facf9fc 29920+
4f0767ce 29921+out:
1facf9fc 29922+ return err;
29923+}
29924+
29925+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
29926+{
29927+ int err;
7f207e10 29928+ struct path h_path;
1facf9fc 29929+ struct super_block *sb;
29930+
29931+ /* lock free root dinfo */
29932+ sb = dentry->d_sb;
29933+ si_noflush_read_lock(sb);
7f207e10 29934+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 29935+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29936+ h_path.mnt = au_sbr_mnt(sb, 0);
29937+ h_path.dentry = h_path.mnt->mnt_root;
29938+ err = vfs_statfs(&h_path, buf);
29939+ } else
1facf9fc 29940+ err = au_statfs_sum(sb, buf);
29941+ si_read_unlock(sb);
29942+
29943+ if (!err) {
29944+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 29945+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 29946+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
29947+ }
29948+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
29949+
29950+ return err;
29951+}
29952+
29953+/* ---------------------------------------------------------------------- */
29954+
537831f9
AM
29955+static int aufs_sync_fs(struct super_block *sb, int wait)
29956+{
29957+ int err, e;
5afbbe0d 29958+ aufs_bindex_t bbot, bindex;
537831f9
AM
29959+ struct au_branch *br;
29960+ struct super_block *h_sb;
29961+
29962+ err = 0;
29963+ si_noflush_read_lock(sb);
5afbbe0d
AM
29964+ bbot = au_sbbot(sb);
29965+ for (bindex = 0; bindex <= bbot; bindex++) {
537831f9
AM
29966+ br = au_sbr(sb, bindex);
29967+ if (!au_br_writable(br->br_perm))
29968+ continue;
29969+
29970+ h_sb = au_sbr_sb(sb, bindex);
a2654f78
AM
29971+ e = vfsub_sync_filesystem(h_sb, wait);
29972+ if (unlikely(e && !err))
29973+ err = e;
29974+ /* go on even if an error happens */
537831f9
AM
29975+ }
29976+ si_read_unlock(sb);
29977+
29978+ return err;
29979+}
29980+
29981+/* ---------------------------------------------------------------------- */
29982+
1facf9fc 29983+/* final actions when unmounting a file system */
29984+static void aufs_put_super(struct super_block *sb)
29985+{
29986+ struct au_sbinfo *sbinfo;
29987+
29988+ sbinfo = au_sbi(sb);
062440b3
AM
29989+ if (sbinfo)
29990+ kobject_put(&sbinfo->si_kobj);
1facf9fc 29991+}
29992+
29993+/* ---------------------------------------------------------------------- */
29994+
79b8bda9
AM
29995+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
29996+ struct super_block *sb, void *arg)
7f207e10
AM
29997+{
29998+ void *array;
076b876e 29999+ unsigned long long n, sz;
7f207e10
AM
30000+
30001+ array = NULL;
30002+ n = 0;
30003+ if (!*hint)
30004+ goto out;
30005+
30006+ if (*hint > ULLONG_MAX / sizeof(array)) {
30007+ array = ERR_PTR(-EMFILE);
30008+ pr_err("hint %llu\n", *hint);
30009+ goto out;
30010+ }
30011+
076b876e
AM
30012+ sz = sizeof(array) * *hint;
30013+ array = kzalloc(sz, GFP_NOFS);
7f207e10 30014+ if (unlikely(!array))
076b876e 30015+ array = vzalloc(sz);
7f207e10
AM
30016+ if (unlikely(!array)) {
30017+ array = ERR_PTR(-ENOMEM);
30018+ goto out;
30019+ }
30020+
79b8bda9 30021+ n = cb(sb, array, *hint, arg);
7f207e10
AM
30022+ AuDebugOn(n > *hint);
30023+
30024+out:
30025+ *hint = n;
30026+ return array;
30027+}
30028+
79b8bda9 30029+static unsigned long long au_iarray_cb(struct super_block *sb, void *a,
7f207e10
AM
30030+ unsigned long long max __maybe_unused,
30031+ void *arg)
30032+{
30033+ unsigned long long n;
30034+ struct inode **p, *inode;
30035+ struct list_head *head;
30036+
30037+ n = 0;
30038+ p = a;
30039+ head = arg;
79b8bda9 30040+ spin_lock(&sb->s_inode_list_lock);
7f207e10 30041+ list_for_each_entry(inode, head, i_sb_list) {
5afbbe0d
AM
30042+ if (!au_is_bad_inode(inode)
30043+ && au_ii(inode)->ii_btop >= 0) {
2cbb1c4b
JR
30044+ spin_lock(&inode->i_lock);
30045+ if (atomic_read(&inode->i_count)) {
30046+ au_igrab(inode);
30047+ *p++ = inode;
30048+ n++;
30049+ AuDebugOn(n > max);
30050+ }
30051+ spin_unlock(&inode->i_lock);
7f207e10
AM
30052+ }
30053+ }
79b8bda9 30054+ spin_unlock(&sb->s_inode_list_lock);
7f207e10
AM
30055+
30056+ return n;
30057+}
30058+
30059+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
30060+{
acd2b654
AM
30061+ struct au_sbinfo *sbi;
30062+
30063+ sbi = au_sbi(sb);
30064+ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1);
79b8bda9 30065+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes);
7f207e10
AM
30066+}
30067+
30068+void au_iarray_free(struct inode **a, unsigned long long max)
30069+{
30070+ unsigned long long ull;
30071+
30072+ for (ull = 0; ull < max; ull++)
30073+ iput(a[ull]);
be52b249 30074+ kvfree(a);
7f207e10
AM
30075+}
30076+
30077+/* ---------------------------------------------------------------------- */
30078+
1facf9fc 30079+/*
30080+ * refresh dentry and inode at remount time.
30081+ */
027c5e7a
AM
30082+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
30083+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
30084+ struct dentry *parent)
1facf9fc 30085+{
30086+ int err;
1facf9fc 30087+
30088+ di_write_lock_child(dentry);
1facf9fc 30089+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
30090+ err = au_refresh_dentry(dentry, parent);
30091+ if (!err && dir_flags)
5527c038 30092+ au_hn_reset(d_inode(dentry), dir_flags);
1facf9fc 30093+ di_read_unlock(parent, AuLock_IR);
1facf9fc 30094+ di_write_unlock(dentry);
30095+
30096+ return err;
30097+}
30098+
027c5e7a
AM
30099+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
30100+ struct au_sbinfo *sbinfo,
b95c5147 30101+ const unsigned int dir_flags, unsigned int do_idop)
1facf9fc 30102+{
027c5e7a
AM
30103+ int err;
30104+ struct dentry *parent;
027c5e7a
AM
30105+
30106+ err = 0;
30107+ parent = dget_parent(dentry);
30108+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
5527c038
JR
30109+ if (d_really_is_positive(dentry)) {
30110+ if (!d_is_dir(dentry))
027c5e7a
AM
30111+ err = au_do_refresh(dentry, /*dir_flags*/0,
30112+ parent);
30113+ else {
30114+ err = au_do_refresh(dentry, dir_flags, parent);
30115+ if (unlikely(err))
30116+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
30117+ }
30118+ } else
30119+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
30120+ AuDbgDentry(dentry);
30121+ }
30122+ dput(parent);
30123+
79b8bda9 30124+ if (!err) {
b95c5147 30125+ if (do_idop)
79b8bda9
AM
30126+ au_refresh_dop(dentry, /*force_reval*/0);
30127+ } else
30128+ au_refresh_dop(dentry, /*force_reval*/1);
30129+
027c5e7a
AM
30130+ AuTraceErr(err);
30131+ return err;
1facf9fc 30132+}
30133+
b95c5147 30134+static int au_refresh_d(struct super_block *sb, unsigned int do_idop)
1facf9fc 30135+{
30136+ int err, i, j, ndentry, e;
027c5e7a 30137+ unsigned int sigen;
1facf9fc 30138+ struct au_dcsub_pages dpages;
30139+ struct au_dpage *dpage;
027c5e7a
AM
30140+ struct dentry **dentries, *d;
30141+ struct au_sbinfo *sbinfo;
30142+ struct dentry *root = sb->s_root;
5527c038 30143+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1);
1facf9fc 30144+
b95c5147 30145+ if (do_idop)
79b8bda9
AM
30146+ au_refresh_dop(root, /*force_reval*/0);
30147+
027c5e7a
AM
30148+ err = au_dpages_init(&dpages, GFP_NOFS);
30149+ if (unlikely(err))
1facf9fc 30150+ goto out;
027c5e7a
AM
30151+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
30152+ if (unlikely(err))
1facf9fc 30153+ goto out_dpages;
1facf9fc 30154+
027c5e7a
AM
30155+ sigen = au_sigen(sb);
30156+ sbinfo = au_sbi(sb);
30157+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 30158+ dpage = dpages.dpages + i;
30159+ dentries = dpage->dentries;
30160+ ndentry = dpage->ndentry;
027c5e7a 30161+ for (j = 0; j < ndentry; j++) {
1facf9fc 30162+ d = dentries[j];
79b8bda9 30163+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags,
b95c5147 30164+ do_idop);
027c5e7a
AM
30165+ if (unlikely(e && !err))
30166+ err = e;
30167+ /* go on even err */
1facf9fc 30168+ }
30169+ }
30170+
4f0767ce 30171+out_dpages:
1facf9fc 30172+ au_dpages_free(&dpages);
4f0767ce 30173+out:
1facf9fc 30174+ return err;
30175+}
30176+
b95c5147 30177+static int au_refresh_i(struct super_block *sb, unsigned int do_idop)
1facf9fc 30178+{
027c5e7a
AM
30179+ int err, e;
30180+ unsigned int sigen;
30181+ unsigned long long max, ull;
30182+ struct inode *inode, **array;
1facf9fc 30183+
027c5e7a
AM
30184+ array = au_iarray_alloc(sb, &max);
30185+ err = PTR_ERR(array);
30186+ if (IS_ERR(array))
30187+ goto out;
1facf9fc 30188+
30189+ err = 0;
027c5e7a
AM
30190+ sigen = au_sigen(sb);
30191+ for (ull = 0; ull < max; ull++) {
30192+ inode = array[ull];
076b876e
AM
30193+ if (unlikely(!inode))
30194+ break;
b95c5147
AM
30195+
30196+ e = 0;
30197+ ii_write_lock_child(inode);
537831f9 30198+ if (au_iigen(inode, NULL) != sigen) {
027c5e7a 30199+ e = au_refresh_hinode_self(inode);
1facf9fc 30200+ if (unlikely(e)) {
b95c5147 30201+ au_refresh_iop(inode, /*force_getattr*/1);
027c5e7a 30202+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 30203+ if (!err)
30204+ err = e;
30205+ /* go on even if err */
30206+ }
30207+ }
b95c5147
AM
30208+ if (!e && do_idop)
30209+ au_refresh_iop(inode, /*force_getattr*/0);
30210+ ii_write_unlock(inode);
1facf9fc 30211+ }
30212+
027c5e7a 30213+ au_iarray_free(array, max);
1facf9fc 30214+
4f0767ce 30215+out:
1facf9fc 30216+ return err;
30217+}
30218+
b95c5147 30219+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
1facf9fc 30220+{
027c5e7a
AM
30221+ int err, e;
30222+ unsigned int udba;
5afbbe0d 30223+ aufs_bindex_t bindex, bbot;
1facf9fc 30224+ struct dentry *root;
30225+ struct inode *inode;
027c5e7a 30226+ struct au_branch *br;
79b8bda9 30227+ struct au_sbinfo *sbi;
1facf9fc 30228+
30229+ au_sigen_inc(sb);
79b8bda9
AM
30230+ sbi = au_sbi(sb);
30231+ au_fclr_si(sbi, FAILED_REFRESH_DIR);
1facf9fc 30232+
30233+ root = sb->s_root;
30234+ DiMustNoWaiters(root);
5527c038 30235+ inode = d_inode(root);
1facf9fc 30236+ IiMustNoWaiters(inode);
1facf9fc 30237+
027c5e7a 30238+ udba = au_opt_udba(sb);
5afbbe0d
AM
30239+ bbot = au_sbbot(sb);
30240+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
30241+ br = au_sbr(sb, bindex);
30242+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 30243+ if (unlikely(err))
027c5e7a
AM
30244+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
30245+ bindex, err);
30246+ /* go on even if err */
1facf9fc 30247+ }
027c5e7a 30248+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 30249+
b95c5147 30250+ if (do_idop) {
79b8bda9
AM
30251+ if (au_ftest_si(sbi, NO_DREVAL)) {
30252+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval);
30253+ sb->s_d_op = &aufs_dop_noreval;
b95c5147
AM
30254+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr);
30255+ sbi->si_iop_array = aufs_iop_nogetattr;
79b8bda9
AM
30256+ } else {
30257+ AuDebugOn(sb->s_d_op == &aufs_dop);
30258+ sb->s_d_op = &aufs_dop;
b95c5147
AM
30259+ AuDebugOn(sbi->si_iop_array == aufs_iop);
30260+ sbi->si_iop_array = aufs_iop;
79b8bda9 30261+ }
062440b3 30262+ pr_info("reset to %ps and %ps\n",
b95c5147 30263+ sb->s_d_op, sbi->si_iop_array);
79b8bda9
AM
30264+ }
30265+
027c5e7a 30266+ di_write_unlock(root);
b95c5147
AM
30267+ err = au_refresh_d(sb, do_idop);
30268+ e = au_refresh_i(sb, do_idop);
027c5e7a
AM
30269+ if (unlikely(e && !err))
30270+ err = e;
1facf9fc 30271+ /* aufs_write_lock() calls ..._child() */
30272+ di_write_lock_child(root);
027c5e7a
AM
30273+
30274+ au_cpup_attr_all(inode, /*force*/1);
30275+
30276+ if (unlikely(err))
30277+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 30278+}
30279+
30280+/* stop extra interpretation of errno in mount(8), and strange error messages */
30281+static int cvt_err(int err)
30282+{
30283+ AuTraceErr(err);
30284+
30285+ switch (err) {
30286+ case -ENOENT:
30287+ case -ENOTDIR:
30288+ case -EEXIST:
30289+ case -EIO:
30290+ err = -EINVAL;
30291+ }
30292+ return err;
30293+}
30294+
30295+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
30296+{
4a4d8108
AM
30297+ int err, do_dx;
30298+ unsigned int mntflags;
be52b249
AM
30299+ struct au_opts opts = {
30300+ .opt = NULL
30301+ };
1facf9fc 30302+ struct dentry *root;
30303+ struct inode *inode;
30304+ struct au_sbinfo *sbinfo;
30305+
30306+ err = 0;
30307+ root = sb->s_root;
30308+ if (!data || !*data) {
e49829fe
JR
30309+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30310+ if (!err) {
30311+ di_write_lock_child(root);
30312+ err = au_opts_verify(sb, *flags, /*pending*/0);
30313+ aufs_write_unlock(root);
30314+ }
1facf9fc 30315+ goto out;
30316+ }
30317+
30318+ err = -ENOMEM;
1facf9fc 30319+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30320+ if (unlikely(!opts.opt))
30321+ goto out;
30322+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30323+ opts.flags = AuOpts_REMOUNT;
30324+ opts.sb_flags = *flags;
30325+
30326+ /* parse it before aufs lock */
30327+ err = au_opts_parse(sb, data, &opts);
30328+ if (unlikely(err))
30329+ goto out_opts;
30330+
30331+ sbinfo = au_sbi(sb);
5527c038 30332+ inode = d_inode(root);
febd17d6 30333+ inode_lock(inode);
e49829fe
JR
30334+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30335+ if (unlikely(err))
30336+ goto out_mtx;
30337+ di_write_lock_child(root);
1facf9fc 30338+
30339+ /* au_opts_remount() may return an error */
30340+ err = au_opts_remount(sb, &opts);
30341+ au_opts_free(&opts);
30342+
027c5e7a 30343+ if (au_ftest_opts(opts.flags, REFRESH))
b95c5147 30344+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP));
1facf9fc 30345+
4a4d8108
AM
30346+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
30347+ mntflags = au_mntflags(sb);
30348+ do_dx = !!au_opt_test(mntflags, DIO);
30349+ au_dy_arefresh(do_dx);
30350+ }
30351+
076b876e 30352+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */
1facf9fc 30353+ aufs_write_unlock(root);
953406b4 30354+
e49829fe 30355+out_mtx:
febd17d6 30356+ inode_unlock(inode);
4f0767ce 30357+out_opts:
1c60b727 30358+ free_page((unsigned long)opts.opt);
4f0767ce 30359+out:
1facf9fc 30360+ err = cvt_err(err);
30361+ AuTraceErr(err);
30362+ return err;
30363+}
30364+
4a4d8108 30365+static const struct super_operations aufs_sop = {
1facf9fc 30366+ .alloc_inode = aufs_alloc_inode,
30367+ .destroy_inode = aufs_destroy_inode,
fbc438ed 30368+ .free_inode = aufs_free_inode,
b752ccd1 30369+ /* always deleting, no clearing */
1facf9fc 30370+ .drop_inode = generic_delete_inode,
30371+ .show_options = aufs_show_options,
30372+ .statfs = aufs_statfs,
30373+ .put_super = aufs_put_super,
537831f9 30374+ .sync_fs = aufs_sync_fs,
1facf9fc 30375+ .remount_fs = aufs_remount_fs
30376+};
30377+
30378+/* ---------------------------------------------------------------------- */
30379+
30380+static int alloc_root(struct super_block *sb)
30381+{
30382+ int err;
30383+ struct inode *inode;
30384+ struct dentry *root;
30385+
30386+ err = -ENOMEM;
30387+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
30388+ err = PTR_ERR(inode);
30389+ if (IS_ERR(inode))
30390+ goto out;
30391+
b95c5147 30392+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */
1facf9fc 30393+ inode->i_fop = &aufs_dir_fop;
30394+ inode->i_mode = S_IFDIR;
9dbd164d 30395+ set_nlink(inode, 2);
1facf9fc 30396+ unlock_new_inode(inode);
30397+
92d182d2 30398+ root = d_make_root(inode);
1facf9fc 30399+ if (unlikely(!root))
92d182d2 30400+ goto out;
1facf9fc 30401+ err = PTR_ERR(root);
30402+ if (IS_ERR(root))
92d182d2 30403+ goto out;
1facf9fc 30404+
4a4d8108 30405+ err = au_di_init(root);
1facf9fc 30406+ if (!err) {
30407+ sb->s_root = root;
30408+ return 0; /* success */
30409+ }
30410+ dput(root);
1facf9fc 30411+
4f0767ce 30412+out:
1facf9fc 30413+ return err;
1facf9fc 30414+}
30415+
30416+static int aufs_fill_super(struct super_block *sb, void *raw_data,
30417+ int silent __maybe_unused)
30418+{
30419+ int err;
be52b249
AM
30420+ struct au_opts opts = {
30421+ .opt = NULL
30422+ };
79b8bda9 30423+ struct au_sbinfo *sbinfo;
1facf9fc 30424+ struct dentry *root;
30425+ struct inode *inode;
30426+ char *arg = raw_data;
30427+
30428+ if (unlikely(!arg || !*arg)) {
30429+ err = -EINVAL;
4a4d8108 30430+ pr_err("no arg\n");
1facf9fc 30431+ goto out;
30432+ }
30433+
30434+ err = -ENOMEM;
1facf9fc 30435+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30436+ if (unlikely(!opts.opt))
30437+ goto out;
30438+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30439+ opts.sb_flags = sb->s_flags;
30440+
30441+ err = au_si_alloc(sb);
30442+ if (unlikely(err))
30443+ goto out_opts;
79b8bda9 30444+ sbinfo = au_sbi(sb);
1facf9fc 30445+
30446+ /* all timestamps always follow the ones on the branch */
2121bcd9 30447+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
be118d29 30448+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */
1facf9fc 30449+ sb->s_op = &aufs_sop;
027c5e7a 30450+ sb->s_d_op = &aufs_dop;
1facf9fc 30451+ sb->s_magic = AUFS_SUPER_MAGIC;
30452+ sb->s_maxbytes = 0;
c1595e42 30453+ sb->s_stack_depth = 1;
1facf9fc 30454+ au_export_init(sb);
f2c43d5f 30455+ au_xattr_init(sb);
1facf9fc 30456+
30457+ err = alloc_root(sb);
30458+ if (unlikely(err)) {
30459+ si_write_unlock(sb);
30460+ goto out_info;
30461+ }
30462+ root = sb->s_root;
5527c038 30463+ inode = d_inode(root);
1facf9fc 30464+
30465+ /*
30466+ * actually we can parse options regardless aufs lock here.
30467+ * but at remount time, parsing must be done before aufs lock.
30468+ * so we follow the same rule.
30469+ */
30470+ ii_write_lock_parent(inode);
30471+ aufs_write_unlock(root);
30472+ err = au_opts_parse(sb, arg, &opts);
30473+ if (unlikely(err))
30474+ goto out_root;
30475+
30476+ /* lock vfs_inode first, then aufs. */
febd17d6 30477+ inode_lock(inode);
1facf9fc 30478+ aufs_write_lock(root);
30479+ err = au_opts_mount(sb, &opts);
30480+ au_opts_free(&opts);
79b8bda9
AM
30481+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
30482+ sb->s_d_op = &aufs_dop_noreval;
062440b3 30483+ pr_info("%ps\n", sb->s_d_op);
79b8bda9 30484+ au_refresh_dop(root, /*force_reval*/0);
b95c5147
AM
30485+ sbinfo->si_iop_array = aufs_iop_nogetattr;
30486+ au_refresh_iop(inode, /*force_getattr*/0);
79b8bda9 30487+ }
1facf9fc 30488+ aufs_write_unlock(root);
febd17d6 30489+ inode_unlock(inode);
4a4d8108
AM
30490+ if (!err)
30491+ goto out_opts; /* success */
1facf9fc 30492+
4f0767ce 30493+out_root:
1facf9fc 30494+ dput(root);
30495+ sb->s_root = NULL;
4f0767ce 30496+out_info:
79b8bda9 30497+ kobject_put(&sbinfo->si_kobj);
1facf9fc 30498+ sb->s_fs_info = NULL;
4f0767ce 30499+out_opts:
1c60b727 30500+ free_page((unsigned long)opts.opt);
4f0767ce 30501+out:
1facf9fc 30502+ AuTraceErr(err);
30503+ err = cvt_err(err);
30504+ AuTraceErr(err);
30505+ return err;
30506+}
30507+
30508+/* ---------------------------------------------------------------------- */
30509+
027c5e7a
AM
30510+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
30511+ const char *dev_name __maybe_unused,
30512+ void *raw_data)
1facf9fc 30513+{
027c5e7a 30514+ struct dentry *root;
1facf9fc 30515+
30516+ /* all timestamps always follow the ones on the branch */
30517+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
30518+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
30519+ if (IS_ERR(root))
30520+ goto out;
30521+
062440b3 30522+ au_sbilist_add(root->d_sb);
027c5e7a
AM
30523+
30524+out:
30525+ return root;
1facf9fc 30526+}
30527+
e49829fe
JR
30528+static void aufs_kill_sb(struct super_block *sb)
30529+{
30530+ struct au_sbinfo *sbinfo;
30531+
30532+ sbinfo = au_sbi(sb);
30533+ if (sbinfo) {
30534+ au_sbilist_del(sb);
30535+ aufs_write_lock(sb->s_root);
076b876e 30536+ au_fhsm_fin(sb);
e49829fe
JR
30537+ if (sbinfo->si_wbr_create_ops->fin)
30538+ sbinfo->si_wbr_create_ops->fin(sb);
30539+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
30540+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
b95c5147 30541+ au_remount_refresh(sb, /*do_idop*/0);
e49829fe
JR
30542+ }
30543+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
30544+ au_plink_put(sb, /*verbose*/1);
30545+ au_xino_clr(sb);
8b6a4947 30546+ au_dr_opt_flush(sb);
1e00d052 30547+ sbinfo->si_sb = NULL;
e49829fe 30548+ aufs_write_unlock(sb->s_root);
e49829fe
JR
30549+ au_nwt_flush(&sbinfo->si_nowait);
30550+ }
98d9a5b1 30551+ kill_anon_super(sb);
e49829fe
JR
30552+}
30553+
1facf9fc 30554+struct file_system_type aufs_fs_type = {
30555+ .name = AUFS_FSTYPE,
c06a8ce3
AM
30556+ /* a race between rename and others */
30557+ .fs_flags = FS_RENAME_DOES_D_MOVE,
027c5e7a 30558+ .mount = aufs_mount,
e49829fe 30559+ .kill_sb = aufs_kill_sb,
1facf9fc 30560+ /* no need to __module_get() and module_put(). */
30561+ .owner = THIS_MODULE,
30562+};
7f207e10 30563diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
eca34b5c
AM
30564--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
30565+++ linux/fs/aufs/super.h 2019-07-11 15:42:14.472238057 +0200
acd2b654 30566@@ -0,0 +1,589 @@
062440b3 30567+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 30568+/*
ba1aed25 30569+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 30570+ *
30571+ * This program, aufs is free software; you can redistribute it and/or modify
30572+ * it under the terms of the GNU General Public License as published by
30573+ * the Free Software Foundation; either version 2 of the License, or
30574+ * (at your option) any later version.
dece6358
AM
30575+ *
30576+ * This program is distributed in the hope that it will be useful,
30577+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30578+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30579+ * GNU General Public License for more details.
30580+ *
30581+ * You should have received a copy of the GNU General Public License
523b37e3 30582+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30583+ */
30584+
30585+/*
30586+ * super_block operations
30587+ */
30588+
30589+#ifndef __AUFS_SUPER_H__
30590+#define __AUFS_SUPER_H__
30591+
30592+#ifdef __KERNEL__
30593+
30594+#include <linux/fs.h>
5527c038 30595+#include <linux/kobject.h>
8b6a4947 30596+#include "hbl.h"
acd2b654 30597+#include "lcnt.h"
1facf9fc 30598+#include "rwsem.h"
1facf9fc 30599+#include "wkq.h"
30600+
1facf9fc 30601+/* policies to select one among multiple writable branches */
30602+struct au_wbr_copyup_operations {
30603+ int (*copyup)(struct dentry *dentry);
30604+};
30605+
392086de
AM
30606+#define AuWbr_DIR 1 /* target is a dir */
30607+#define AuWbr_PARENT (1 << 1) /* always require a parent */
30608+
30609+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name)
30610+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; }
30611+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; }
30612+
1facf9fc 30613+struct au_wbr_create_operations {
392086de 30614+ int (*create)(struct dentry *dentry, unsigned int flags);
1facf9fc 30615+ int (*init)(struct super_block *sb);
30616+ int (*fin)(struct super_block *sb);
30617+};
30618+
30619+struct au_wbr_mfs {
30620+ struct mutex mfs_lock; /* protect this structure */
30621+ unsigned long mfs_jiffy;
30622+ unsigned long mfs_expire;
30623+ aufs_bindex_t mfs_bindex;
30624+
30625+ unsigned long long mfsrr_bytes;
30626+ unsigned long long mfsrr_watermark;
30627+};
30628+
86dc4139
AM
30629+#define AuPlink_NHASH 100
30630+static inline int au_plink_hash(ino_t ino)
30631+{
30632+ return ino % AuPlink_NHASH;
30633+}
30634+
076b876e
AM
30635+/* File-based Hierarchical Storage Management */
30636+struct au_fhsm {
30637+#ifdef CONFIG_AUFS_FHSM
30638+ /* allow only one process who can receive the notification */
30639+ spinlock_t fhsm_spin;
30640+ pid_t fhsm_pid;
30641+ wait_queue_head_t fhsm_wqh;
30642+ atomic_t fhsm_readable;
30643+
c1595e42 30644+ /* these are protected by si_rwsem */
076b876e 30645+ unsigned long fhsm_expire;
c1595e42 30646+ aufs_bindex_t fhsm_bottom;
076b876e
AM
30647+#endif
30648+};
30649+
1facf9fc 30650+struct au_branch;
30651+struct au_sbinfo {
30652+ /* nowait tasks in the system-wide workqueue */
30653+ struct au_nowait_tasks si_nowait;
30654+
b752ccd1 30655+ /*
acd2b654 30656+ * tried sb->s_umount, but failed due to the dependency between i_mutex.
b752ccd1
AM
30657+ * rwsem for au_sbinfo is necessary.
30658+ */
dece6358 30659+ struct au_rwsem si_rwsem;
1facf9fc 30660+
7f207e10 30661+ /*
523b37e3
AM
30662+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from
30663+ * remount.
7f207e10 30664+ */
acd2b654 30665+ au_lcnt_t si_ninodes, si_nfiles;
7f207e10 30666+
1facf9fc 30667+ /* branch management */
30668+ unsigned int si_generation;
30669+
2000de60 30670+ /* see AuSi_ flags */
1facf9fc 30671+ unsigned char au_si_status;
30672+
5afbbe0d 30673+ aufs_bindex_t si_bbot;
7f207e10
AM
30674+
30675+ /* dirty trick to keep br_id plus */
30676+ unsigned int si_last_br_id :
30677+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 30678+ struct au_branch **si_branch;
30679+
30680+ /* policy to select a writable branch */
30681+ unsigned char si_wbr_copyup;
30682+ unsigned char si_wbr_create;
30683+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
30684+ struct au_wbr_create_operations *si_wbr_create_ops;
30685+
30686+ /* round robin */
30687+ atomic_t si_wbr_rr_next;
30688+
30689+ /* most free space */
30690+ struct au_wbr_mfs si_wbr_mfs;
30691+
076b876e
AM
30692+ /* File-based Hierarchical Storage Management */
30693+ struct au_fhsm si_fhsm;
30694+
1facf9fc 30695+ /* mount flags */
30696+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
30697+ unsigned int si_mntflags;
30698+
30699+ /* external inode number (bitmap and translation table) */
5527c038
JR
30700+ vfs_readf_t si_xread;
30701+ vfs_writef_t si_xwrite;
acd2b654
AM
30702+ loff_t si_ximaxent; /* max entries in a xino */
30703+
1facf9fc 30704+ struct file *si_xib;
30705+ struct mutex si_xib_mtx; /* protect xib members */
30706+ unsigned long *si_xib_buf;
30707+ unsigned long si_xib_last_pindex;
30708+ int si_xib_next_bit;
acd2b654 30709+
392086de
AM
30710+ unsigned long si_xino_jiffy;
30711+ unsigned long si_xino_expire;
1facf9fc 30712+ /* reserved for future use */
30713+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
30714+
30715+#ifdef CONFIG_AUFS_EXPORT
30716+ /* i_generation */
acd2b654 30717+ /* todo: make xigen file an array to support many inode numbers */
1facf9fc 30718+ struct file *si_xigen;
30719+ atomic_t si_xigen_next;
30720+#endif
30721+
acd2b654 30722+ /* dirty trick to support atomic_open */
8b6a4947 30723+ struct hlist_bl_head si_aopen;
b912730e 30724+
1facf9fc 30725+ /* vdir parameters */
e49829fe 30726+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 30727+ unsigned int si_rdblk; /* deblk size */
30728+ unsigned int si_rdhash; /* hash size */
30729+
30730+ /*
30731+ * If the number of whiteouts are larger than si_dirwh, leave all of
30732+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
30733+ * future fsck.aufs or kernel thread will remove them later.
30734+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
30735+ */
30736+ unsigned int si_dirwh;
30737+
1facf9fc 30738+ /* pseudo_link list */
8b6a4947 30739+ struct hlist_bl_head si_plink[AuPlink_NHASH];
1facf9fc 30740+ wait_queue_head_t si_plink_wq;
4a4d8108 30741+ spinlock_t si_plink_maint_lock;
e49829fe 30742+ pid_t si_plink_maint_pid;
1facf9fc 30743+
523b37e3 30744+ /* file list */
8b6a4947 30745+ struct hlist_bl_head si_files;
523b37e3 30746+
b95c5147
AM
30747+ /* with/without getattr, brother of sb->s_d_op */
30748+ struct inode_operations *si_iop_array;
30749+
1facf9fc 30750+ /*
30751+ * sysfs and lifetime management.
30752+ * this is not a small structure and it may be a waste of memory in case
acd2b654 30753+ * of sysfs is disabled, particularly when many aufs-es are mounted.
1facf9fc 30754+ * but using sysfs is majority.
30755+ */
30756+ struct kobject si_kobj;
30757+#ifdef CONFIG_DEBUG_FS
86dc4139
AM
30758+ struct dentry *si_dbgaufs;
30759+ struct dentry *si_dbgaufs_plink;
30760+ struct dentry *si_dbgaufs_xib;
1facf9fc 30761+#ifdef CONFIG_AUFS_EXPORT
30762+ struct dentry *si_dbgaufs_xigen;
30763+#endif
30764+#endif
30765+
e49829fe 30766+#ifdef CONFIG_AUFS_SBILIST
8b6a4947 30767+ struct hlist_bl_node si_list;
e49829fe
JR
30768+#endif
30769+
1facf9fc 30770+ /* dirty, necessary for unmounting, sysfs and sysrq */
30771+ struct super_block *si_sb;
30772+};
30773+
dece6358
AM
30774+/* sbinfo status flags */
30775+/*
30776+ * set true when refresh_dirs() failed at remount time.
30777+ * then try refreshing dirs at access time again.
062440b3 30778+ * if it is false, refreshing dirs at access time is unnecessary
dece6358 30779+ */
027c5e7a 30780+#define AuSi_FAILED_REFRESH_DIR 1
076b876e 30781+#define AuSi_FHSM (1 << 1) /* fhsm is active now */
79b8bda9 30782+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */
076b876e
AM
30783+
30784+#ifndef CONFIG_AUFS_FHSM
30785+#undef AuSi_FHSM
30786+#define AuSi_FHSM 0
30787+#endif
30788+
dece6358
AM
30789+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
30790+ unsigned int flag)
30791+{
30792+ AuRwMustAnyLock(&sbi->si_rwsem);
30793+ return sbi->au_si_status & flag;
30794+}
30795+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
30796+#define au_fset_si(sbinfo, name) do { \
30797+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30798+ (sbinfo)->au_si_status |= AuSi_##name; \
30799+} while (0)
30800+#define au_fclr_si(sbinfo, name) do { \
30801+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30802+ (sbinfo)->au_si_status &= ~AuSi_##name; \
30803+} while (0)
30804+
1facf9fc 30805+/* ---------------------------------------------------------------------- */
30806+
30807+/* policy to select one among writable branches */
4a4d8108
AM
30808+#define AuWbrCopyup(sbinfo, ...) \
30809+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
30810+#define AuWbrCreate(sbinfo, ...) \
30811+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 30812+
30813+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
30814+#define AuLock_DW 1 /* write-lock dentry */
30815+#define AuLock_IR (1 << 1) /* read-lock inode */
30816+#define AuLock_IW (1 << 2) /* write-lock inode */
30817+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
b95c5147 30818+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */
f2c43d5f 30819+ /* except RENAME_EXCHANGE */
e49829fe
JR
30820+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
30821+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 30822+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 30823+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
30824+#define au_fset_lock(flags, name) \
30825+ do { (flags) |= AuLock_##name; } while (0)
30826+#define au_fclr_lock(flags, name) \
30827+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 30828+
30829+/* ---------------------------------------------------------------------- */
30830+
30831+/* super.c */
30832+extern struct file_system_type aufs_fs_type;
30833+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
79b8bda9
AM
30834+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array,
30835+ unsigned long long max, void *arg);
79b8bda9
AM
30836+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
30837+ struct super_block *sb, void *arg);
7f207e10
AM
30838+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
30839+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 30840+
30841+/* sbinfo.c */
30842+void au_si_free(struct kobject *kobj);
30843+int au_si_alloc(struct super_block *sb);
e2f27e51 30844+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink);
1facf9fc 30845+
30846+unsigned int au_sigen_inc(struct super_block *sb);
30847+aufs_bindex_t au_new_br_id(struct super_block *sb);
30848+
e49829fe
JR
30849+int si_read_lock(struct super_block *sb, int flags);
30850+int si_write_lock(struct super_block *sb, int flags);
30851+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 30852+void aufs_read_unlock(struct dentry *dentry, int flags);
30853+void aufs_write_lock(struct dentry *dentry);
30854+void aufs_write_unlock(struct dentry *dentry);
e49829fe 30855+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 30856+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
30857+
30858+/* wbr_policy.c */
30859+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
30860+extern struct au_wbr_create_operations au_wbr_create_ops[];
30861+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
c2b27bf2 30862+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex);
5afbbe0d 30863+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop);
c2b27bf2
AM
30864+
30865+/* mvdown.c */
30866+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg);
1facf9fc 30867+
076b876e
AM
30868+#ifdef CONFIG_AUFS_FHSM
30869+/* fhsm.c */
30870+
30871+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm)
30872+{
30873+ pid_t pid;
30874+
30875+ spin_lock(&fhsm->fhsm_spin);
30876+ pid = fhsm->fhsm_pid;
30877+ spin_unlock(&fhsm->fhsm_spin);
30878+
30879+ return pid;
30880+}
30881+
30882+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force);
30883+void au_fhsm_wrote_all(struct super_block *sb, int force);
30884+int au_fhsm_fd(struct super_block *sb, int oflags);
30885+int au_fhsm_br_alloc(struct au_branch *br);
c1595e42 30886+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex);
076b876e
AM
30887+void au_fhsm_fin(struct super_block *sb);
30888+void au_fhsm_init(struct au_sbinfo *sbinfo);
30889+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec);
30890+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo);
30891+#else
30892+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex,
30893+ int force)
30894+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force)
30895+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags)
c1595e42
JR
30896+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm)
30897+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br)
30898+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex)
076b876e
AM
30899+AuStubVoid(au_fhsm_fin, struct super_block *sb)
30900+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo)
30901+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec)
30902+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo)
30903+#endif
30904+
1facf9fc 30905+/* ---------------------------------------------------------------------- */
30906+
30907+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
30908+{
30909+ return sb->s_fs_info;
30910+}
30911+
30912+/* ---------------------------------------------------------------------- */
30913+
30914+#ifdef CONFIG_AUFS_EXPORT
a2a7ad62 30915+int au_test_nfsd(void);
1facf9fc 30916+void au_export_init(struct super_block *sb);
b752ccd1 30917+void au_xigen_inc(struct inode *inode);
1facf9fc 30918+int au_xigen_new(struct inode *inode);
062440b3 30919+int au_xigen_set(struct super_block *sb, struct path *path);
1facf9fc 30920+void au_xigen_clr(struct super_block *sb);
30921+
30922+static inline int au_busy_or_stale(void)
30923+{
b752ccd1 30924+ if (!au_test_nfsd())
1facf9fc 30925+ return -EBUSY;
30926+ return -ESTALE;
30927+}
30928+#else
b752ccd1 30929+AuStubInt0(au_test_nfsd, void)
a2a7ad62 30930+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1 30931+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108 30932+AuStubInt0(au_xigen_new, struct inode *inode)
062440b3 30933+AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path)
4a4d8108 30934+AuStubVoid(au_xigen_clr, struct super_block *sb)
c1595e42 30935+AuStub(int, au_busy_or_stale, return -EBUSY, void)
1facf9fc 30936+#endif /* CONFIG_AUFS_EXPORT */
30937+
30938+/* ---------------------------------------------------------------------- */
30939+
e49829fe
JR
30940+#ifdef CONFIG_AUFS_SBILIST
30941+/* module.c */
8b6a4947 30942+extern struct hlist_bl_head au_sbilist;
e49829fe
JR
30943+
30944+static inline void au_sbilist_init(void)
30945+{
8b6a4947 30946+ INIT_HLIST_BL_HEAD(&au_sbilist);
e49829fe
JR
30947+}
30948+
30949+static inline void au_sbilist_add(struct super_block *sb)
30950+{
8b6a4947 30951+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe
JR
30952+}
30953+
30954+static inline void au_sbilist_del(struct super_block *sb)
30955+{
8b6a4947 30956+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe 30957+}
53392da6
AM
30958+
30959+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
30960+static inline void au_sbilist_lock(void)
30961+{
8b6a4947 30962+ hlist_bl_lock(&au_sbilist);
53392da6
AM
30963+}
30964+
30965+static inline void au_sbilist_unlock(void)
30966+{
8b6a4947 30967+ hlist_bl_unlock(&au_sbilist);
53392da6
AM
30968+}
30969+#define AuGFP_SBILIST GFP_ATOMIC
30970+#else
30971+AuStubVoid(au_sbilist_lock, void)
30972+AuStubVoid(au_sbilist_unlock, void)
30973+#define AuGFP_SBILIST GFP_NOFS
30974+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
30975+#else
30976+AuStubVoid(au_sbilist_init, void)
c1595e42
JR
30977+AuStubVoid(au_sbilist_add, struct super_block *sb)
30978+AuStubVoid(au_sbilist_del, struct super_block *sb)
53392da6
AM
30979+AuStubVoid(au_sbilist_lock, void)
30980+AuStubVoid(au_sbilist_unlock, void)
30981+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
30982+#endif
30983+
30984+/* ---------------------------------------------------------------------- */
30985+
1facf9fc 30986+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
30987+{
dece6358 30988+ /*
c1595e42 30989+ * This function is a dynamic '__init' function actually,
dece6358
AM
30990+ * so the tiny check for si_rwsem is unnecessary.
30991+ */
30992+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 30993+#ifdef CONFIG_DEBUG_FS
30994+ sbinfo->si_dbgaufs = NULL;
86dc4139 30995+ sbinfo->si_dbgaufs_plink = NULL;
1facf9fc 30996+ sbinfo->si_dbgaufs_xib = NULL;
30997+#ifdef CONFIG_AUFS_EXPORT
30998+ sbinfo->si_dbgaufs_xigen = NULL;
30999+#endif
31000+#endif
31001+}
31002+
31003+/* ---------------------------------------------------------------------- */
31004+
a2654f78
AM
31005+/* current->atomic_flags */
31006+/* this value should never corrupt the ones defined in linux/sched.h */
fbc438ed 31007+#define PFA_AUFS 0x10
a2654f78
AM
31008+
31009+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */
31010+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */
31011+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */
b752ccd1
AM
31012+
31013+static inline int si_pid_test(struct super_block *sb)
31014+{
a2654f78 31015+ return !!task_test_aufs(current);
b752ccd1
AM
31016+}
31017+
31018+static inline void si_pid_clr(struct super_block *sb)
31019+{
a2654f78
AM
31020+ AuDebugOn(!task_test_aufs(current));
31021+ task_clear_aufs(current);
b752ccd1
AM
31022+}
31023+
a2654f78
AM
31024+static inline void si_pid_set(struct super_block *sb)
31025+{
31026+ AuDebugOn(task_test_aufs(current));
31027+ task_set_aufs(current);
31028+}
febd17d6 31029+
b752ccd1
AM
31030+/* ---------------------------------------------------------------------- */
31031+
1facf9fc 31032+/* lock superblock. mainly for entry point functions */
8b6a4947
AM
31033+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem)
31034+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem)
31035+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem)
31036+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem)
31037+/*
31038+#define __si_read_trylock_nested(sb) \
31039+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem)
31040+#define __si_write_trylock_nested(sb) \
31041+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem)
31042+*/
31043+
31044+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem)
31045+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem)
31046+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem)
1facf9fc 31047+
dece6358
AM
31048+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
31049+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
31050+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
31051+
b752ccd1
AM
31052+static inline void si_noflush_read_lock(struct super_block *sb)
31053+{
31054+ __si_read_lock(sb);
31055+ si_pid_set(sb);
31056+}
31057+
31058+static inline int si_noflush_read_trylock(struct super_block *sb)
31059+{
076b876e
AM
31060+ int locked;
31061+
31062+ locked = __si_read_trylock(sb);
b752ccd1
AM
31063+ if (locked)
31064+ si_pid_set(sb);
31065+ return locked;
31066+}
31067+
31068+static inline void si_noflush_write_lock(struct super_block *sb)
31069+{
31070+ __si_write_lock(sb);
31071+ si_pid_set(sb);
31072+}
31073+
31074+static inline int si_noflush_write_trylock(struct super_block *sb)
31075+{
076b876e
AM
31076+ int locked;
31077+
31078+ locked = __si_write_trylock(sb);
b752ccd1
AM
31079+ if (locked)
31080+ si_pid_set(sb);
31081+ return locked;
31082+}
31083+
7e9cd9fe 31084+#if 0 /* reserved */
1facf9fc 31085+static inline int si_read_trylock(struct super_block *sb, int flags)
31086+{
31087+ if (au_ftest_lock(flags, FLUSH))
31088+ au_nwt_flush(&au_sbi(sb)->si_nowait);
31089+ return si_noflush_read_trylock(sb);
31090+}
e49829fe 31091+#endif
1facf9fc 31092+
b752ccd1
AM
31093+static inline void si_read_unlock(struct super_block *sb)
31094+{
31095+ si_pid_clr(sb);
31096+ __si_read_unlock(sb);
31097+}
31098+
7e9cd9fe 31099+#if 0 /* reserved */
1facf9fc 31100+static inline int si_write_trylock(struct super_block *sb, int flags)
31101+{
31102+ if (au_ftest_lock(flags, FLUSH))
31103+ au_nwt_flush(&au_sbi(sb)->si_nowait);
31104+ return si_noflush_write_trylock(sb);
31105+}
b752ccd1
AM
31106+#endif
31107+
31108+static inline void si_write_unlock(struct super_block *sb)
31109+{
31110+ si_pid_clr(sb);
31111+ __si_write_unlock(sb);
31112+}
31113+
7e9cd9fe 31114+#if 0 /* reserved */
b752ccd1
AM
31115+static inline void si_downgrade_lock(struct super_block *sb)
31116+{
31117+ __si_downgrade_lock(sb);
31118+}
31119+#endif
1facf9fc 31120+
31121+/* ---------------------------------------------------------------------- */
31122+
5afbbe0d 31123+static inline aufs_bindex_t au_sbbot(struct super_block *sb)
1facf9fc 31124+{
dece6358 31125+ SiMustAnyLock(sb);
5afbbe0d 31126+ return au_sbi(sb)->si_bbot;
1facf9fc 31127+}
31128+
31129+static inline unsigned int au_mntflags(struct super_block *sb)
31130+{
dece6358 31131+ SiMustAnyLock(sb);
1facf9fc 31132+ return au_sbi(sb)->si_mntflags;
31133+}
31134+
31135+static inline unsigned int au_sigen(struct super_block *sb)
31136+{
dece6358 31137+ SiMustAnyLock(sb);
1facf9fc 31138+ return au_sbi(sb)->si_generation;
31139+}
31140+
31141+static inline struct au_branch *au_sbr(struct super_block *sb,
31142+ aufs_bindex_t bindex)
31143+{
dece6358 31144+ SiMustAnyLock(sb);
1facf9fc 31145+ return au_sbi(sb)->si_branch[0 + bindex];
31146+}
31147+
acd2b654 31148+static inline loff_t au_xi_maxent(struct super_block *sb)
1facf9fc 31149+{
dece6358 31150+ SiMustAnyLock(sb);
acd2b654 31151+ return au_sbi(sb)->si_ximaxent;
1facf9fc 31152+}
31153+
31154+#endif /* __KERNEL__ */
31155+#endif /* __AUFS_SUPER_H__ */
7f207e10 31156diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
eca34b5c
AM
31157--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
31158+++ linux/fs/aufs/sysaufs.c 2019-07-11 15:42:14.472238057 +0200
062440b3 31159@@ -0,0 +1,93 @@
cd7a4cd9 31160+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31161+/*
ba1aed25 31162+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31163+ *
31164+ * This program, aufs is free software; you can redistribute it and/or modify
31165+ * it under the terms of the GNU General Public License as published by
31166+ * the Free Software Foundation; either version 2 of the License, or
31167+ * (at your option) any later version.
dece6358
AM
31168+ *
31169+ * This program is distributed in the hope that it will be useful,
31170+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31171+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31172+ * GNU General Public License for more details.
31173+ *
31174+ * You should have received a copy of the GNU General Public License
523b37e3 31175+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31176+ */
31177+
31178+/*
31179+ * sysfs interface and lifetime management
31180+ * they are necessary regardless sysfs is disabled.
31181+ */
31182+
1facf9fc 31183+#include <linux/random.h>
1facf9fc 31184+#include "aufs.h"
31185+
31186+unsigned long sysaufs_si_mask;
e49829fe 31187+struct kset *sysaufs_kset;
1facf9fc 31188+
31189+#define AuSiAttr(_name) { \
31190+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
31191+ .show = sysaufs_si_##_name, \
31192+}
31193+
31194+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
31195+struct attribute *sysaufs_si_attrs[] = {
31196+ &sysaufs_si_attr_xi_path.attr,
31197+ NULL,
31198+};
31199+
4a4d8108 31200+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 31201+ .show = sysaufs_si_show
31202+};
31203+
31204+static struct kobj_type au_sbi_ktype = {
31205+ .release = au_si_free,
31206+ .sysfs_ops = &au_sbi_ops,
31207+ .default_attrs = sysaufs_si_attrs
31208+};
31209+
31210+/* ---------------------------------------------------------------------- */
31211+
31212+int sysaufs_si_init(struct au_sbinfo *sbinfo)
31213+{
31214+ int err;
31215+
e49829fe 31216+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 31217+ /* cf. sysaufs_name() */
31218+ err = kobject_init_and_add
e49829fe 31219+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 31220+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
31221+
1facf9fc 31222+ return err;
31223+}
31224+
31225+void sysaufs_fin(void)
31226+{
e49829fe
JR
31227+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
31228+ kset_unregister(sysaufs_kset);
1facf9fc 31229+}
31230+
31231+int __init sysaufs_init(void)
31232+{
31233+ int err;
31234+
31235+ do {
31236+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
31237+ } while (!sysaufs_si_mask);
31238+
4a4d8108 31239+ err = -EINVAL;
e49829fe
JR
31240+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
31241+ if (unlikely(!sysaufs_kset))
4a4d8108 31242+ goto out;
e49829fe
JR
31243+ err = PTR_ERR(sysaufs_kset);
31244+ if (IS_ERR(sysaufs_kset))
1facf9fc 31245+ goto out;
e49829fe 31246+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
062440b3 31247+ if (unlikely(err))
e49829fe 31248+ kset_unregister(sysaufs_kset);
1facf9fc 31249+
4f0767ce 31250+out:
1facf9fc 31251+ return err;
31252+}
7f207e10 31253diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
eca34b5c
AM
31254--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
31255+++ linux/fs/aufs/sysaufs.h 2019-07-11 15:42:14.475571481 +0200
062440b3
AM
31256@@ -0,0 +1,102 @@
31257+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 31258+/*
ba1aed25 31259+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31260+ *
31261+ * This program, aufs is free software; you can redistribute it and/or modify
31262+ * it under the terms of the GNU General Public License as published by
31263+ * the Free Software Foundation; either version 2 of the License, or
31264+ * (at your option) any later version.
dece6358
AM
31265+ *
31266+ * This program is distributed in the hope that it will be useful,
31267+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31268+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31269+ * GNU General Public License for more details.
31270+ *
31271+ * You should have received a copy of the GNU General Public License
523b37e3 31272+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31273+ */
31274+
31275+/*
31276+ * sysfs interface and mount lifetime management
31277+ */
31278+
31279+#ifndef __SYSAUFS_H__
31280+#define __SYSAUFS_H__
31281+
31282+#ifdef __KERNEL__
31283+
1facf9fc 31284+#include <linux/sysfs.h>
1facf9fc 31285+#include "module.h"
31286+
dece6358
AM
31287+struct super_block;
31288+struct au_sbinfo;
31289+
1facf9fc 31290+struct sysaufs_si_attr {
31291+ struct attribute attr;
31292+ int (*show)(struct seq_file *seq, struct super_block *sb);
31293+};
31294+
31295+/* ---------------------------------------------------------------------- */
31296+
31297+/* sysaufs.c */
31298+extern unsigned long sysaufs_si_mask;
e49829fe 31299+extern struct kset *sysaufs_kset;
1facf9fc 31300+extern struct attribute *sysaufs_si_attrs[];
31301+int sysaufs_si_init(struct au_sbinfo *sbinfo);
31302+int __init sysaufs_init(void);
31303+void sysaufs_fin(void);
31304+
31305+/* ---------------------------------------------------------------------- */
31306+
31307+/* some people doesn't like to show a pointer in kernel */
31308+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
31309+{
31310+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
31311+}
31312+
31313+#define SysaufsSiNamePrefix "si_"
31314+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
31315+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
31316+{
31317+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
31318+ sysaufs_si_id(sbinfo));
31319+}
31320+
31321+struct au_branch;
31322+#ifdef CONFIG_SYSFS
31323+/* sysfs.c */
31324+extern struct attribute_group *sysaufs_attr_group;
31325+
31326+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
31327+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
31328+ char *buf);
076b876e
AM
31329+long au_brinfo_ioctl(struct file *file, unsigned long arg);
31330+#ifdef CONFIG_COMPAT
31331+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg);
31332+#endif
1facf9fc 31333+
31334+void sysaufs_br_init(struct au_branch *br);
31335+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
31336+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
31337+
31338+#define sysaufs_brs_init() do {} while (0)
31339+
31340+#else
31341+#define sysaufs_attr_group NULL
31342+
4a4d8108 31343+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
c1595e42
JR
31344+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj,
31345+ struct attribute *attr, char *buf)
4a4d8108
AM
31346+AuStubVoid(sysaufs_br_init, struct au_branch *br)
31347+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
31348+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 31349+
31350+static inline void sysaufs_brs_init(void)
31351+{
31352+ sysaufs_brs = 0;
31353+}
31354+
31355+#endif /* CONFIG_SYSFS */
31356+
31357+#endif /* __KERNEL__ */
31358+#endif /* __SYSAUFS_H__ */
7f207e10 31359diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
eca34b5c
AM
31360--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
31361+++ linux/fs/aufs/sysfs.c 2019-07-11 15:42:14.475571481 +0200
ba1aed25 31362@@ -0,0 +1,374 @@
cd7a4cd9 31363+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31364+/*
ba1aed25 31365+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31366+ *
31367+ * This program, aufs is free software; you can redistribute it and/or modify
31368+ * it under the terms of the GNU General Public License as published by
31369+ * the Free Software Foundation; either version 2 of the License, or
31370+ * (at your option) any later version.
dece6358
AM
31371+ *
31372+ * This program is distributed in the hope that it will be useful,
31373+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31374+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31375+ * GNU General Public License for more details.
31376+ *
31377+ * You should have received a copy of the GNU General Public License
523b37e3 31378+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31379+ */
31380+
31381+/*
31382+ * sysfs interface
31383+ */
31384+
076b876e 31385+#include <linux/compat.h>
1facf9fc 31386+#include <linux/seq_file.h>
1facf9fc 31387+#include "aufs.h"
31388+
4a4d8108
AM
31389+#ifdef CONFIG_AUFS_FS_MODULE
31390+/* this entry violates the "one line per file" policy of sysfs */
31391+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
31392+ char *buf)
31393+{
31394+ ssize_t err;
31395+ static char *conf =
31396+/* this file is generated at compiling */
31397+#include "conf.str"
31398+ ;
31399+
31400+ err = snprintf(buf, PAGE_SIZE, conf);
31401+ if (unlikely(err >= PAGE_SIZE))
31402+ err = -EFBIG;
31403+ return err;
31404+}
31405+
31406+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
31407+#endif
31408+
1facf9fc 31409+static struct attribute *au_attr[] = {
4a4d8108
AM
31410+#ifdef CONFIG_AUFS_FS_MODULE
31411+ &au_config_attr.attr,
31412+#endif
1facf9fc 31413+ NULL, /* need to NULL terminate the list of attributes */
31414+};
31415+
31416+static struct attribute_group sysaufs_attr_group_body = {
31417+ .attrs = au_attr
31418+};
31419+
31420+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
31421+
31422+/* ---------------------------------------------------------------------- */
31423+
31424+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
31425+{
31426+ int err;
31427+
dece6358
AM
31428+ SiMustAnyLock(sb);
31429+
1facf9fc 31430+ err = 0;
31431+ if (au_opt_test(au_mntflags(sb), XINO)) {
31432+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
31433+ seq_putc(seq, '\n');
31434+ }
31435+ return err;
31436+}
31437+
31438+/*
31439+ * the lifetime of branch is independent from the entry under sysfs.
31440+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
31441+ * unlinked.
31442+ */
31443+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
392086de 31444+ aufs_bindex_t bindex, int idx)
1facf9fc 31445+{
1e00d052 31446+ int err;
1facf9fc 31447+ struct path path;
31448+ struct dentry *root;
31449+ struct au_branch *br;
076b876e 31450+ au_br_perm_str_t perm;
1facf9fc 31451+
31452+ AuDbg("b%d\n", bindex);
31453+
1e00d052 31454+ err = 0;
1facf9fc 31455+ root = sb->s_root;
31456+ di_read_lock_parent(root, !AuLock_IR);
31457+ br = au_sbr(sb, bindex);
392086de
AM
31458+
31459+ switch (idx) {
31460+ case AuBrSysfs_BR:
31461+ path.mnt = au_br_mnt(br);
31462+ path.dentry = au_h_dptr(root, bindex);
79b8bda9
AM
31463+ err = au_seq_path(seq, &path);
31464+ if (!err) {
31465+ au_optstr_br_perm(&perm, br->br_perm);
31466+ seq_printf(seq, "=%s\n", perm.a);
31467+ }
392086de
AM
31468+ break;
31469+ case AuBrSysfs_BRID:
79b8bda9 31470+ seq_printf(seq, "%d\n", br->br_id);
392086de
AM
31471+ break;
31472+ }
076b876e 31473+ di_read_unlock(root, !AuLock_IR);
79b8bda9 31474+ if (unlikely(err || seq_has_overflowed(seq)))
076b876e 31475+ err = -E2BIG;
392086de 31476+
1e00d052 31477+ return err;
1facf9fc 31478+}
31479+
31480+/* ---------------------------------------------------------------------- */
31481+
31482+static struct seq_file *au_seq(char *p, ssize_t len)
31483+{
31484+ struct seq_file *seq;
31485+
31486+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
31487+ if (seq) {
31488+ /* mutex_init(&seq.lock); */
31489+ seq->buf = p;
31490+ seq->size = len;
31491+ return seq; /* success */
31492+ }
31493+
31494+ seq = ERR_PTR(-ENOMEM);
31495+ return seq;
31496+}
31497+
392086de
AM
31498+#define SysaufsBr_PREFIX "br"
31499+#define SysaufsBrid_PREFIX "brid"
1facf9fc 31500+
31501+/* todo: file size may exceed PAGE_SIZE */
31502+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 31503+ char *buf)
1facf9fc 31504+{
31505+ ssize_t err;
392086de 31506+ int idx;
1facf9fc 31507+ long l;
5afbbe0d 31508+ aufs_bindex_t bbot;
1facf9fc 31509+ struct au_sbinfo *sbinfo;
31510+ struct super_block *sb;
31511+ struct seq_file *seq;
31512+ char *name;
31513+ struct attribute **cattr;
31514+
31515+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
31516+ sb = sbinfo->si_sb;
1308ab2a 31517+
31518+ /*
31519+ * prevent a race condition between sysfs and aufs.
31520+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
31521+ * prohibits maintaining the sysfs entries.
31522+ * hew we acquire read lock after sysfs_get_active_two().
31523+ * on the other hand, the remount process may maintain the sysfs/aufs
31524+ * entries after acquiring write lock.
31525+ * it can cause a deadlock.
31526+ * simply we gave up processing read here.
31527+ */
31528+ err = -EBUSY;
31529+ if (unlikely(!si_noflush_read_trylock(sb)))
31530+ goto out;
1facf9fc 31531+
31532+ seq = au_seq(buf, PAGE_SIZE);
31533+ err = PTR_ERR(seq);
31534+ if (IS_ERR(seq))
1308ab2a 31535+ goto out_unlock;
1facf9fc 31536+
31537+ name = (void *)attr->name;
31538+ cattr = sysaufs_si_attrs;
31539+ while (*cattr) {
31540+ if (!strcmp(name, (*cattr)->name)) {
31541+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
31542+ ->show(seq, sb);
31543+ goto out_seq;
31544+ }
31545+ cattr++;
31546+ }
31547+
392086de
AM
31548+ if (!strncmp(name, SysaufsBrid_PREFIX,
31549+ sizeof(SysaufsBrid_PREFIX) - 1)) {
31550+ idx = AuBrSysfs_BRID;
31551+ name += sizeof(SysaufsBrid_PREFIX) - 1;
31552+ } else if (!strncmp(name, SysaufsBr_PREFIX,
31553+ sizeof(SysaufsBr_PREFIX) - 1)) {
31554+ idx = AuBrSysfs_BR;
1facf9fc 31555+ name += sizeof(SysaufsBr_PREFIX) - 1;
392086de
AM
31556+ } else
31557+ BUG();
31558+
31559+ err = kstrtol(name, 10, &l);
31560+ if (!err) {
5afbbe0d
AM
31561+ bbot = au_sbbot(sb);
31562+ if (l <= bbot)
392086de
AM
31563+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx);
31564+ else
31565+ err = -ENOENT;
1facf9fc 31566+ }
1facf9fc 31567+
4f0767ce 31568+out_seq:
1facf9fc 31569+ if (!err) {
31570+ err = seq->count;
31571+ /* sysfs limit */
31572+ if (unlikely(err == PAGE_SIZE))
31573+ err = -EFBIG;
31574+ }
9f237c51 31575+ au_kfree_rcu(seq);
4f0767ce 31576+out_unlock:
1facf9fc 31577+ si_read_unlock(sb);
4f0767ce 31578+out:
1facf9fc 31579+ return err;
31580+}
31581+
31582+/* ---------------------------------------------------------------------- */
31583+
076b876e
AM
31584+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg)
31585+{
31586+ int err;
31587+ int16_t brid;
5afbbe0d 31588+ aufs_bindex_t bindex, bbot;
076b876e
AM
31589+ size_t sz;
31590+ char *buf;
31591+ struct seq_file *seq;
31592+ struct au_branch *br;
31593+
31594+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d
AM
31595+ bbot = au_sbbot(sb);
31596+ err = bbot + 1;
076b876e
AM
31597+ if (!arg)
31598+ goto out;
31599+
31600+ err = -ENOMEM;
31601+ buf = (void *)__get_free_page(GFP_NOFS);
31602+ if (unlikely(!buf))
31603+ goto out;
31604+
31605+ seq = au_seq(buf, PAGE_SIZE);
31606+ err = PTR_ERR(seq);
31607+ if (IS_ERR(seq))
31608+ goto out_buf;
31609+
31610+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path);
5afbbe0d 31611+ for (bindex = 0; bindex <= bbot; bindex++, arg++) {
ba1aed25
AM
31612+ /* VERIFY_WRITE */
31613+ err = !access_ok(arg, sizeof(*arg));
076b876e
AM
31614+ if (unlikely(err))
31615+ break;
31616+
31617+ br = au_sbr(sb, bindex);
31618+ brid = br->br_id;
31619+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id));
31620+ err = __put_user(brid, &arg->id);
31621+ if (unlikely(err))
31622+ break;
31623+
31624+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm));
31625+ err = __put_user(br->br_perm, &arg->perm);
31626+ if (unlikely(err))
31627+ break;
31628+
79b8bda9
AM
31629+ err = au_seq_path(seq, &br->br_path);
31630+ if (unlikely(err))
31631+ break;
31632+ seq_putc(seq, '\0');
31633+ if (!seq_has_overflowed(seq)) {
076b876e
AM
31634+ err = copy_to_user(arg->path, seq->buf, seq->count);
31635+ seq->count = 0;
31636+ if (unlikely(err))
31637+ break;
31638+ } else {
31639+ err = -E2BIG;
31640+ goto out_seq;
31641+ }
31642+ }
31643+ if (unlikely(err))
31644+ err = -EFAULT;
31645+
31646+out_seq:
9f237c51 31647+ au_kfree_rcu(seq);
076b876e 31648+out_buf:
1c60b727 31649+ free_page((unsigned long)buf);
076b876e
AM
31650+out:
31651+ si_read_unlock(sb);
31652+ return err;
31653+}
31654+
31655+long au_brinfo_ioctl(struct file *file, unsigned long arg)
31656+{
2000de60 31657+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg);
076b876e
AM
31658+}
31659+
31660+#ifdef CONFIG_COMPAT
31661+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg)
31662+{
2000de60 31663+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg));
076b876e
AM
31664+}
31665+#endif
31666+
31667+/* ---------------------------------------------------------------------- */
31668+
1facf9fc 31669+void sysaufs_br_init(struct au_branch *br)
31670+{
392086de
AM
31671+ int i;
31672+ struct au_brsysfs *br_sysfs;
31673+ struct attribute *attr;
4a4d8108 31674+
392086de
AM
31675+ br_sysfs = br->br_sysfs;
31676+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31677+ attr = &br_sysfs->attr;
31678+ sysfs_attr_init(attr);
31679+ attr->name = br_sysfs->name;
cd7a4cd9 31680+ attr->mode = 0444;
392086de
AM
31681+ br_sysfs++;
31682+ }
1facf9fc 31683+}
31684+
31685+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
31686+{
31687+ struct au_branch *br;
31688+ struct kobject *kobj;
392086de
AM
31689+ struct au_brsysfs *br_sysfs;
31690+ int i;
5afbbe0d 31691+ aufs_bindex_t bbot;
1facf9fc 31692+
1facf9fc 31693+ if (!sysaufs_brs)
31694+ return;
31695+
31696+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31697+ bbot = au_sbbot(sb);
31698+ for (; bindex <= bbot; bindex++) {
1facf9fc 31699+ br = au_sbr(sb, bindex);
392086de
AM
31700+ br_sysfs = br->br_sysfs;
31701+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31702+ sysfs_remove_file(kobj, &br_sysfs->attr);
31703+ br_sysfs++;
31704+ }
1facf9fc 31705+ }
31706+}
31707+
31708+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
31709+{
392086de 31710+ int err, i;
5afbbe0d 31711+ aufs_bindex_t bbot;
1facf9fc 31712+ struct kobject *kobj;
31713+ struct au_branch *br;
392086de 31714+ struct au_brsysfs *br_sysfs;
1facf9fc 31715+
1facf9fc 31716+ if (!sysaufs_brs)
31717+ return;
31718+
31719+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31720+ bbot = au_sbbot(sb);
31721+ for (; bindex <= bbot; bindex++) {
1facf9fc 31722+ br = au_sbr(sb, bindex);
392086de
AM
31723+ br_sysfs = br->br_sysfs;
31724+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name),
31725+ SysaufsBr_PREFIX "%d", bindex);
31726+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name),
31727+ SysaufsBrid_PREFIX "%d", bindex);
31728+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31729+ err = sysfs_create_file(kobj, &br_sysfs->attr);
31730+ if (unlikely(err))
31731+ pr_warn("failed %s under sysfs(%d)\n",
31732+ br_sysfs->name, err);
31733+ br_sysfs++;
31734+ }
1facf9fc 31735+ }
31736+}
7f207e10 31737diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
eca34b5c
AM
31738--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
31739+++ linux/fs/aufs/sysrq.c 2019-07-11 15:42:14.475571481 +0200
062440b3 31740@@ -0,0 +1,160 @@
cd7a4cd9 31741+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31742+/*
ba1aed25 31743+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31744+ *
31745+ * This program, aufs is free software; you can redistribute it and/or modify
31746+ * it under the terms of the GNU General Public License as published by
31747+ * the Free Software Foundation; either version 2 of the License, or
31748+ * (at your option) any later version.
dece6358
AM
31749+ *
31750+ * This program is distributed in the hope that it will be useful,
31751+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31752+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31753+ * GNU General Public License for more details.
31754+ *
31755+ * You should have received a copy of the GNU General Public License
523b37e3 31756+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31757+ */
31758+
31759+/*
acd2b654 31760+ * magic sysrq handler
1facf9fc 31761+ */
31762+
1facf9fc 31763+/* #include <linux/sysrq.h> */
027c5e7a 31764+#include <linux/writeback.h>
1facf9fc 31765+#include "aufs.h"
31766+
31767+/* ---------------------------------------------------------------------- */
31768+
31769+static void sysrq_sb(struct super_block *sb)
31770+{
31771+ char *plevel;
31772+ struct au_sbinfo *sbinfo;
31773+ struct file *file;
8b6a4947
AM
31774+ struct hlist_bl_head *files;
31775+ struct hlist_bl_node *pos;
523b37e3 31776+ struct au_finfo *finfo;
1facf9fc 31777+
31778+ plevel = au_plevel;
31779+ au_plevel = KERN_WARNING;
1facf9fc 31780+
4a4d8108 31781+ /* since we define pr_fmt, call printk directly */
c06a8ce3
AM
31782+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str)
31783+
31784+ sbinfo = au_sbi(sb);
4a4d8108 31785+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
c06a8ce3 31786+ pr("superblock\n");
1facf9fc 31787+ au_dpri_sb(sb);
027c5e7a
AM
31788+
31789+#if 0
c06a8ce3 31790+ pr("root dentry\n");
1facf9fc 31791+ au_dpri_dentry(sb->s_root);
c06a8ce3 31792+ pr("root inode\n");
5527c038 31793+ au_dpri_inode(d_inode(sb->s_root));
027c5e7a
AM
31794+#endif
31795+
1facf9fc 31796+#if 0
027c5e7a
AM
31797+ do {
31798+ int err, i, j, ndentry;
31799+ struct au_dcsub_pages dpages;
31800+ struct au_dpage *dpage;
31801+
31802+ err = au_dpages_init(&dpages, GFP_ATOMIC);
31803+ if (unlikely(err))
31804+ break;
31805+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
31806+ if (!err)
31807+ for (i = 0; i < dpages.ndpage; i++) {
31808+ dpage = dpages.dpages + i;
31809+ ndentry = dpage->ndentry;
31810+ for (j = 0; j < ndentry; j++)
31811+ au_dpri_dentry(dpage->dentries[j]);
31812+ }
31813+ au_dpages_free(&dpages);
31814+ } while (0);
31815+#endif
31816+
31817+#if 1
31818+ {
31819+ struct inode *i;
076b876e 31820+
c06a8ce3 31821+ pr("isolated inode\n");
79b8bda9 31822+ spin_lock(&sb->s_inode_list_lock);
2cbb1c4b
JR
31823+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
31824+ spin_lock(&i->i_lock);
b4510431 31825+ if (1 || hlist_empty(&i->i_dentry))
027c5e7a 31826+ au_dpri_inode(i);
2cbb1c4b
JR
31827+ spin_unlock(&i->i_lock);
31828+ }
79b8bda9 31829+ spin_unlock(&sb->s_inode_list_lock);
027c5e7a 31830+ }
1facf9fc 31831+#endif
c06a8ce3 31832+ pr("files\n");
523b37e3 31833+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
31834+ hlist_bl_lock(files);
31835+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
4a4d8108 31836+ umode_t mode;
076b876e 31837+
523b37e3 31838+ file = finfo->fi_file;
c06a8ce3 31839+ mode = file_inode(file)->i_mode;
38d290e6 31840+ if (!special_file(mode))
1facf9fc 31841+ au_dpri_file(file);
523b37e3 31842+ }
8b6a4947 31843+ hlist_bl_unlock(files);
c06a8ce3 31844+ pr("done\n");
1facf9fc 31845+
c06a8ce3 31846+#undef pr
1facf9fc 31847+ au_plevel = plevel;
1facf9fc 31848+}
31849+
31850+/* ---------------------------------------------------------------------- */
31851+
31852+/* module parameter */
31853+static char *aufs_sysrq_key = "a";
cd7a4cd9 31854+module_param_named(sysrq, aufs_sysrq_key, charp, 0444);
1facf9fc 31855+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
31856+
0c5527e5 31857+static void au_sysrq(int key __maybe_unused)
1facf9fc 31858+{
1facf9fc 31859+ struct au_sbinfo *sbinfo;
8b6a4947 31860+ struct hlist_bl_node *pos;
1facf9fc 31861+
027c5e7a 31862+ lockdep_off();
53392da6 31863+ au_sbilist_lock();
8b6a4947 31864+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
1facf9fc 31865+ sysrq_sb(sbinfo->si_sb);
53392da6 31866+ au_sbilist_unlock();
027c5e7a 31867+ lockdep_on();
1facf9fc 31868+}
31869+
31870+static struct sysrq_key_op au_sysrq_op = {
31871+ .handler = au_sysrq,
31872+ .help_msg = "Aufs",
31873+ .action_msg = "Aufs",
31874+ .enable_mask = SYSRQ_ENABLE_DUMP
31875+};
31876+
31877+/* ---------------------------------------------------------------------- */
31878+
31879+int __init au_sysrq_init(void)
31880+{
31881+ int err;
31882+ char key;
31883+
31884+ err = -1;
31885+ key = *aufs_sysrq_key;
31886+ if ('a' <= key && key <= 'z')
31887+ err = register_sysrq_key(key, &au_sysrq_op);
31888+ if (unlikely(err))
4a4d8108 31889+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 31890+ return err;
31891+}
31892+
31893+void au_sysrq_fin(void)
31894+{
31895+ int err;
076b876e 31896+
1facf9fc 31897+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
31898+ if (unlikely(err))
4a4d8108 31899+ pr_err("err %d (ignored)\n", err);
1facf9fc 31900+}
7f207e10 31901diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
eca34b5c
AM
31902--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
31903+++ linux/fs/aufs/vdir.c 2019-07-11 15:42:14.475571481 +0200
eca801bf 31904@@ -0,0 +1,896 @@
cd7a4cd9 31905+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31906+/*
ba1aed25 31907+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31908+ *
31909+ * This program, aufs is free software; you can redistribute it and/or modify
31910+ * it under the terms of the GNU General Public License as published by
31911+ * the Free Software Foundation; either version 2 of the License, or
31912+ * (at your option) any later version.
dece6358
AM
31913+ *
31914+ * This program is distributed in the hope that it will be useful,
31915+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31916+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31917+ * GNU General Public License for more details.
31918+ *
31919+ * You should have received a copy of the GNU General Public License
523b37e3 31920+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31921+ */
31922+
31923+/*
31924+ * virtual or vertical directory
31925+ */
31926+
eca801bf 31927+#include <linux/iversion.h>
1facf9fc 31928+#include "aufs.h"
31929+
dece6358 31930+static unsigned int calc_size(int nlen)
1facf9fc 31931+{
dece6358 31932+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 31933+}
31934+
31935+static int set_deblk_end(union au_vdir_deblk_p *p,
31936+ union au_vdir_deblk_p *deblk_end)
31937+{
31938+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
31939+ p->de->de_str.len = 0;
31940+ /* smp_mb(); */
31941+ return 0;
31942+ }
31943+ return -1; /* error */
31944+}
31945+
31946+/* returns true or false */
31947+static int is_deblk_end(union au_vdir_deblk_p *p,
31948+ union au_vdir_deblk_p *deblk_end)
31949+{
31950+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
31951+ return !p->de->de_str.len;
31952+ return 1;
31953+}
31954+
31955+static unsigned char *last_deblk(struct au_vdir *vdir)
31956+{
31957+ return vdir->vd_deblk[vdir->vd_nblk - 1];
31958+}
31959+
31960+/* ---------------------------------------------------------------------- */
31961+
79b8bda9 31962+/* estimate the appropriate size for name hash table */
1308ab2a 31963+unsigned int au_rdhash_est(loff_t sz)
31964+{
31965+ unsigned int n;
31966+
31967+ n = UINT_MAX;
31968+ sz >>= 10;
31969+ if (sz < n)
31970+ n = sz;
31971+ if (sz < AUFS_RDHASH_DEF)
31972+ n = AUFS_RDHASH_DEF;
4a4d8108 31973+ /* pr_info("n %u\n", n); */
1308ab2a 31974+ return n;
31975+}
31976+
1facf9fc 31977+/*
31978+ * the allocated memory has to be freed by
dece6358 31979+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 31980+ */
dece6358 31981+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 31982+{
1facf9fc 31983+ struct hlist_head *head;
dece6358 31984+ unsigned int u;
076b876e 31985+ size_t sz;
1facf9fc 31986+
076b876e
AM
31987+ sz = sizeof(*nhash->nh_head) * num_hash;
31988+ head = kmalloc(sz, gfp);
dece6358
AM
31989+ if (head) {
31990+ nhash->nh_num = num_hash;
31991+ nhash->nh_head = head;
31992+ for (u = 0; u < num_hash; u++)
1facf9fc 31993+ INIT_HLIST_HEAD(head++);
dece6358 31994+ return 0; /* success */
1facf9fc 31995+ }
1facf9fc 31996+
dece6358 31997+ return -ENOMEM;
1facf9fc 31998+}
31999+
dece6358
AM
32000+static void nhash_count(struct hlist_head *head)
32001+{
32002+#if 0
32003+ unsigned long n;
32004+ struct hlist_node *pos;
32005+
32006+ n = 0;
32007+ hlist_for_each(pos, head)
32008+ n++;
4a4d8108 32009+ pr_info("%lu\n", n);
dece6358
AM
32010+#endif
32011+}
32012+
32013+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 32014+{
c06a8ce3
AM
32015+ struct au_vdir_wh *pos;
32016+ struct hlist_node *node;
1facf9fc 32017+
c06a8ce3 32018+ hlist_for_each_entry_safe(pos, node, head, wh_hash)
9f237c51 32019+ au_kfree_rcu(pos);
1facf9fc 32020+}
32021+
dece6358 32022+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 32023+{
c06a8ce3
AM
32024+ struct au_vdir_dehstr *pos;
32025+ struct hlist_node *node;
1facf9fc 32026+
c06a8ce3 32027+ hlist_for_each_entry_safe(pos, node, head, hash)
1c60b727 32028+ au_cache_free_vdir_dehstr(pos);
1facf9fc 32029+}
32030+
dece6358
AM
32031+static void au_nhash_do_free(struct au_nhash *nhash,
32032+ void (*free)(struct hlist_head *head))
1facf9fc 32033+{
1308ab2a 32034+ unsigned int n;
1facf9fc 32035+ struct hlist_head *head;
1facf9fc 32036+
dece6358 32037+ n = nhash->nh_num;
1308ab2a 32038+ if (!n)
32039+ return;
32040+
dece6358 32041+ head = nhash->nh_head;
1308ab2a 32042+ while (n-- > 0) {
dece6358
AM
32043+ nhash_count(head);
32044+ free(head++);
1facf9fc 32045+ }
9f237c51 32046+ au_kfree_try_rcu(nhash->nh_head);
1facf9fc 32047+}
32048+
dece6358 32049+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 32050+{
dece6358
AM
32051+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
32052+}
1facf9fc 32053+
dece6358
AM
32054+static void au_nhash_de_free(struct au_nhash *delist)
32055+{
32056+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 32057+}
32058+
32059+/* ---------------------------------------------------------------------- */
32060+
32061+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
32062+ int limit)
32063+{
32064+ int num;
32065+ unsigned int u, n;
32066+ struct hlist_head *head;
c06a8ce3 32067+ struct au_vdir_wh *pos;
1facf9fc 32068+
32069+ num = 0;
32070+ n = whlist->nh_num;
32071+ head = whlist->nh_head;
1308ab2a 32072+ for (u = 0; u < n; u++, head++)
c06a8ce3
AM
32073+ hlist_for_each_entry(pos, head, wh_hash)
32074+ if (pos->wh_bindex == btgt && ++num > limit)
1facf9fc 32075+ return 1;
1facf9fc 32076+ return 0;
32077+}
32078+
32079+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 32080+ unsigned char *name,
1facf9fc 32081+ unsigned int len)
32082+{
dece6358
AM
32083+ unsigned int v;
32084+ /* const unsigned int magic_bit = 12; */
32085+
1308ab2a 32086+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
32087+
dece6358 32088+ v = 0;
f0c0a007
AM
32089+ if (len > 8)
32090+ len = 8;
dece6358
AM
32091+ while (len--)
32092+ v += *name++;
32093+ /* v = hash_long(v, magic_bit); */
32094+ v %= nhash->nh_num;
32095+ return nhash->nh_head + v;
32096+}
32097+
32098+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
32099+ int nlen)
32100+{
32101+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 32102+}
32103+
32104+/* returns found or not */
dece6358 32105+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 32106+{
32107+ struct hlist_head *head;
c06a8ce3 32108+ struct au_vdir_wh *pos;
1facf9fc 32109+ struct au_vdir_destr *str;
32110+
dece6358 32111+ head = au_name_hash(whlist, name, nlen);
c06a8ce3
AM
32112+ hlist_for_each_entry(pos, head, wh_hash) {
32113+ str = &pos->wh_str;
1facf9fc 32114+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
32115+ if (au_nhash_test_name(str, name, nlen))
32116+ return 1;
32117+ }
32118+ return 0;
32119+}
32120+
32121+/* returns found(true) or not */
32122+static int test_known(struct au_nhash *delist, char *name, int nlen)
32123+{
32124+ struct hlist_head *head;
c06a8ce3 32125+ struct au_vdir_dehstr *pos;
dece6358
AM
32126+ struct au_vdir_destr *str;
32127+
32128+ head = au_name_hash(delist, name, nlen);
c06a8ce3
AM
32129+ hlist_for_each_entry(pos, head, hash) {
32130+ str = pos->str;
dece6358
AM
32131+ AuDbg("%.*s\n", str->len, str->name);
32132+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 32133+ return 1;
32134+ }
32135+ return 0;
32136+}
32137+
dece6358
AM
32138+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
32139+ unsigned char d_type)
32140+{
32141+#ifdef CONFIG_AUFS_SHWH
32142+ wh->wh_ino = ino;
32143+ wh->wh_type = d_type;
32144+#endif
32145+}
32146+
32147+/* ---------------------------------------------------------------------- */
32148+
32149+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
32150+ unsigned int d_type, aufs_bindex_t bindex,
32151+ unsigned char shwh)
1facf9fc 32152+{
32153+ int err;
32154+ struct au_vdir_destr *str;
32155+ struct au_vdir_wh *wh;
32156+
dece6358 32157+ AuDbg("%.*s\n", nlen, name);
1308ab2a 32158+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
32159+
1facf9fc 32160+ err = -ENOMEM;
dece6358 32161+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 32162+ if (unlikely(!wh))
32163+ goto out;
32164+
32165+ err = 0;
32166+ wh->wh_bindex = bindex;
dece6358
AM
32167+ if (shwh)
32168+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 32169+ str = &wh->wh_str;
dece6358
AM
32170+ str->len = nlen;
32171+ memcpy(str->name, name, nlen);
32172+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 32173+ /* smp_mb(); */
32174+
4f0767ce 32175+out:
1facf9fc 32176+ return err;
32177+}
32178+
1facf9fc 32179+static int append_deblk(struct au_vdir *vdir)
32180+{
32181+ int err;
dece6358 32182+ unsigned long ul;
1facf9fc 32183+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32184+ union au_vdir_deblk_p p, deblk_end;
32185+ unsigned char **o;
32186+
32187+ err = -ENOMEM;
e2f27e51
AM
32188+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
32189+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32190+ if (unlikely(!o))
32191+ goto out;
32192+
32193+ vdir->vd_deblk = o;
32194+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
32195+ if (p.deblk) {
32196+ ul = vdir->vd_nblk++;
32197+ vdir->vd_deblk[ul] = p.deblk;
32198+ vdir->vd_last.ul = ul;
32199+ vdir->vd_last.p.deblk = p.deblk;
32200+ deblk_end.deblk = p.deblk + deblk_sz;
32201+ err = set_deblk_end(&p, &deblk_end);
32202+ }
32203+
4f0767ce 32204+out:
1facf9fc 32205+ return err;
32206+}
32207+
dece6358
AM
32208+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
32209+ unsigned int d_type, struct au_nhash *delist)
32210+{
32211+ int err;
32212+ unsigned int sz;
32213+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32214+ union au_vdir_deblk_p p, *room, deblk_end;
32215+ struct au_vdir_dehstr *dehstr;
32216+
32217+ p.deblk = last_deblk(vdir);
32218+ deblk_end.deblk = p.deblk + deblk_sz;
32219+ room = &vdir->vd_last.p;
32220+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
32221+ || !is_deblk_end(room, &deblk_end));
32222+
32223+ sz = calc_size(nlen);
32224+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
32225+ err = append_deblk(vdir);
32226+ if (unlikely(err))
32227+ goto out;
32228+
32229+ p.deblk = last_deblk(vdir);
32230+ deblk_end.deblk = p.deblk + deblk_sz;
32231+ /* smp_mb(); */
32232+ AuDebugOn(room->deblk != p.deblk);
32233+ }
32234+
32235+ err = -ENOMEM;
4a4d8108 32236+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
32237+ if (unlikely(!dehstr))
32238+ goto out;
32239+
32240+ dehstr->str = &room->de->de_str;
32241+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
32242+ room->de->de_ino = ino;
32243+ room->de->de_type = d_type;
32244+ room->de->de_str.len = nlen;
32245+ memcpy(room->de->de_str.name, name, nlen);
32246+
32247+ err = 0;
32248+ room->deblk += sz;
32249+ if (unlikely(set_deblk_end(room, &deblk_end)))
32250+ err = append_deblk(vdir);
32251+ /* smp_mb(); */
32252+
4f0767ce 32253+out:
dece6358
AM
32254+ return err;
32255+}
32256+
32257+/* ---------------------------------------------------------------------- */
32258+
1c60b727 32259+void au_vdir_free(struct au_vdir *vdir)
dece6358
AM
32260+{
32261+ unsigned char **deblk;
32262+
32263+ deblk = vdir->vd_deblk;
1c60b727 32264+ while (vdir->vd_nblk--)
9f237c51
AM
32265+ au_kfree_try_rcu(*deblk++);
32266+ au_kfree_try_rcu(vdir->vd_deblk);
1c60b727 32267+ au_cache_free_vdir(vdir);
dece6358
AM
32268+}
32269+
1308ab2a 32270+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 32271+{
32272+ struct au_vdir *vdir;
1308ab2a 32273+ struct super_block *sb;
1facf9fc 32274+ int err;
32275+
2000de60 32276+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32277+ SiMustAnyLock(sb);
32278+
1facf9fc 32279+ err = -ENOMEM;
32280+ vdir = au_cache_alloc_vdir();
32281+ if (unlikely(!vdir))
32282+ goto out;
32283+
32284+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
32285+ if (unlikely(!vdir->vd_deblk))
32286+ goto out_free;
32287+
32288+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 32289+ if (!vdir->vd_deblk_sz) {
79b8bda9 32290+ /* estimate the appropriate size for deblk */
1308ab2a 32291+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 32292+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 32293+ }
1facf9fc 32294+ vdir->vd_nblk = 0;
32295+ vdir->vd_version = 0;
32296+ vdir->vd_jiffy = 0;
32297+ err = append_deblk(vdir);
32298+ if (!err)
32299+ return vdir; /* success */
32300+
9f237c51 32301+ au_kfree_try_rcu(vdir->vd_deblk);
1facf9fc 32302+
4f0767ce 32303+out_free:
1c60b727 32304+ au_cache_free_vdir(vdir);
4f0767ce 32305+out:
1facf9fc 32306+ vdir = ERR_PTR(err);
32307+ return vdir;
32308+}
32309+
32310+static int reinit_vdir(struct au_vdir *vdir)
32311+{
32312+ int err;
32313+ union au_vdir_deblk_p p, deblk_end;
32314+
32315+ while (vdir->vd_nblk > 1) {
9f237c51 32316+ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]);
1facf9fc 32317+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
32318+ vdir->vd_nblk--;
32319+ }
32320+ p.deblk = vdir->vd_deblk[0];
32321+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
32322+ err = set_deblk_end(&p, &deblk_end);
32323+ /* keep vd_dblk_sz */
32324+ vdir->vd_last.ul = 0;
32325+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32326+ vdir->vd_version = 0;
32327+ vdir->vd_jiffy = 0;
32328+ /* smp_mb(); */
32329+ return err;
32330+}
32331+
32332+/* ---------------------------------------------------------------------- */
32333+
1facf9fc 32334+#define AuFillVdir_CALLED 1
32335+#define AuFillVdir_WHABLE (1 << 1)
dece6358 32336+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 32337+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
32338+#define au_fset_fillvdir(flags, name) \
32339+ do { (flags) |= AuFillVdir_##name; } while (0)
32340+#define au_fclr_fillvdir(flags, name) \
32341+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 32342+
dece6358
AM
32343+#ifndef CONFIG_AUFS_SHWH
32344+#undef AuFillVdir_SHWH
32345+#define AuFillVdir_SHWH 0
32346+#endif
32347+
1facf9fc 32348+struct fillvdir_arg {
392086de 32349+ struct dir_context ctx;
1facf9fc 32350+ struct file *file;
32351+ struct au_vdir *vdir;
dece6358
AM
32352+ struct au_nhash delist;
32353+ struct au_nhash whlist;
1facf9fc 32354+ aufs_bindex_t bindex;
32355+ unsigned int flags;
32356+ int err;
32357+};
32358+
392086de 32359+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen,
1facf9fc 32360+ loff_t offset __maybe_unused, u64 h_ino,
32361+ unsigned int d_type)
32362+{
392086de 32363+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx);
1facf9fc 32364+ char *name = (void *)__name;
32365+ struct super_block *sb;
1facf9fc 32366+ ino_t ino;
dece6358 32367+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 32368+
1facf9fc 32369+ arg->err = 0;
2000de60 32370+ sb = arg->file->f_path.dentry->d_sb;
1facf9fc 32371+ au_fset_fillvdir(arg->flags, CALLED);
32372+ /* smp_mb(); */
dece6358 32373+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 32374+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
32375+ if (test_known(&arg->delist, name, nlen)
32376+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
32377+ goto out; /* already exists or whiteouted */
1facf9fc 32378+
dece6358 32379+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
32380+ if (!arg->err) {
32381+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
32382+ d_type = DT_UNKNOWN;
dece6358
AM
32383+ arg->err = append_de(arg->vdir, name, nlen, ino,
32384+ d_type, &arg->delist);
4a4d8108 32385+ }
1facf9fc 32386+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
32387+ name += AUFS_WH_PFX_LEN;
dece6358
AM
32388+ nlen -= AUFS_WH_PFX_LEN;
32389+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
32390+ goto out; /* already whiteouted */
1facf9fc 32391+
acd2b654 32392+ ino = 0; /* just to suppress a warning */
dece6358
AM
32393+ if (shwh)
32394+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
32395+ &ino);
4a4d8108
AM
32396+ if (!arg->err) {
32397+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
32398+ d_type = DT_UNKNOWN;
1facf9fc 32399+ arg->err = au_nhash_append_wh
dece6358
AM
32400+ (&arg->whlist, name, nlen, ino, d_type,
32401+ arg->bindex, shwh);
4a4d8108 32402+ }
1facf9fc 32403+ }
32404+
4f0767ce 32405+out:
1facf9fc 32406+ if (!arg->err)
32407+ arg->vdir->vd_jiffy = jiffies;
32408+ /* smp_mb(); */
32409+ AuTraceErr(arg->err);
32410+ return arg->err;
32411+}
32412+
dece6358
AM
32413+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
32414+ struct au_nhash *whlist, struct au_nhash *delist)
32415+{
32416+#ifdef CONFIG_AUFS_SHWH
32417+ int err;
32418+ unsigned int nh, u;
32419+ struct hlist_head *head;
c06a8ce3
AM
32420+ struct au_vdir_wh *pos;
32421+ struct hlist_node *n;
dece6358
AM
32422+ char *p, *o;
32423+ struct au_vdir_destr *destr;
32424+
32425+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
32426+
32427+ err = -ENOMEM;
537831f9 32428+ o = p = (void *)__get_free_page(GFP_NOFS);
dece6358
AM
32429+ if (unlikely(!p))
32430+ goto out;
32431+
32432+ err = 0;
32433+ nh = whlist->nh_num;
32434+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
32435+ p += AUFS_WH_PFX_LEN;
32436+ for (u = 0; u < nh; u++) {
32437+ head = whlist->nh_head + u;
c06a8ce3
AM
32438+ hlist_for_each_entry_safe(pos, n, head, wh_hash) {
32439+ destr = &pos->wh_str;
dece6358
AM
32440+ memcpy(p, destr->name, destr->len);
32441+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
c06a8ce3 32442+ pos->wh_ino, pos->wh_type, delist);
dece6358
AM
32443+ if (unlikely(err))
32444+ break;
32445+ }
32446+ }
32447+
1c60b727 32448+ free_page((unsigned long)o);
dece6358 32449+
4f0767ce 32450+out:
dece6358
AM
32451+ AuTraceErr(err);
32452+ return err;
32453+#else
32454+ return 0;
32455+#endif
32456+}
32457+
1facf9fc 32458+static int au_do_read_vdir(struct fillvdir_arg *arg)
32459+{
32460+ int err;
dece6358 32461+ unsigned int rdhash;
1facf9fc 32462+ loff_t offset;
5afbbe0d 32463+ aufs_bindex_t bbot, bindex, btop;
dece6358 32464+ unsigned char shwh;
1facf9fc 32465+ struct file *hf, *file;
32466+ struct super_block *sb;
32467+
1facf9fc 32468+ file = arg->file;
2000de60 32469+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32470+ SiMustAnyLock(sb);
32471+
32472+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 32473+ if (!rdhash)
32474+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
32475+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
32476+ if (unlikely(err))
1facf9fc 32477+ goto out;
dece6358
AM
32478+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
32479+ if (unlikely(err))
1facf9fc 32480+ goto out_delist;
32481+
32482+ err = 0;
32483+ arg->flags = 0;
dece6358
AM
32484+ shwh = 0;
32485+ if (au_opt_test(au_mntflags(sb), SHWH)) {
32486+ shwh = 1;
32487+ au_fset_fillvdir(arg->flags, SHWH);
32488+ }
5afbbe0d
AM
32489+ btop = au_fbtop(file);
32490+ bbot = au_fbbot_dir(file);
32491+ for (bindex = btop; !err && bindex <= bbot; bindex++) {
4a4d8108 32492+ hf = au_hf_dir(file, bindex);
1facf9fc 32493+ if (!hf)
32494+ continue;
32495+
32496+ offset = vfsub_llseek(hf, 0, SEEK_SET);
32497+ err = offset;
32498+ if (unlikely(offset))
32499+ break;
32500+
32501+ arg->bindex = bindex;
32502+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358 32503+ if (shwh
5afbbe0d 32504+ || (bindex != bbot
dece6358 32505+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 32506+ au_fset_fillvdir(arg->flags, WHABLE);
32507+ do {
32508+ arg->err = 0;
32509+ au_fclr_fillvdir(arg->flags, CALLED);
32510+ /* smp_mb(); */
392086de 32511+ err = vfsub_iterate_dir(hf, &arg->ctx);
1facf9fc 32512+ if (err >= 0)
32513+ err = arg->err;
32514+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
392086de
AM
32515+
32516+ /*
32517+ * dir_relax() may be good for concurrency, but aufs should not
32518+ * use it since it will cause a lockdep problem.
32519+ */
1facf9fc 32520+ }
dece6358
AM
32521+
32522+ if (!err && shwh)
32523+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
32524+
32525+ au_nhash_wh_free(&arg->whlist);
1facf9fc 32526+
4f0767ce 32527+out_delist:
dece6358 32528+ au_nhash_de_free(&arg->delist);
4f0767ce 32529+out:
1facf9fc 32530+ return err;
32531+}
32532+
32533+static int read_vdir(struct file *file, int may_read)
32534+{
32535+ int err;
32536+ unsigned long expire;
32537+ unsigned char do_read;
392086de
AM
32538+ struct fillvdir_arg arg = {
32539+ .ctx = {
2000de60 32540+ .actor = fillvdir
392086de
AM
32541+ }
32542+ };
1facf9fc 32543+ struct inode *inode;
32544+ struct au_vdir *vdir, *allocated;
32545+
32546+ err = 0;
c06a8ce3 32547+ inode = file_inode(file);
1facf9fc 32548+ IMustLock(inode);
5afbbe0d 32549+ IiMustWriteLock(inode);
dece6358
AM
32550+ SiMustAnyLock(inode->i_sb);
32551+
1facf9fc 32552+ allocated = NULL;
32553+ do_read = 0;
32554+ expire = au_sbi(inode->i_sb)->si_rdcache;
32555+ vdir = au_ivdir(inode);
32556+ if (!vdir) {
32557+ do_read = 1;
1308ab2a 32558+ vdir = alloc_vdir(file);
1facf9fc 32559+ err = PTR_ERR(vdir);
32560+ if (IS_ERR(vdir))
32561+ goto out;
32562+ err = 0;
32563+ allocated = vdir;
32564+ } else if (may_read
be118d29 32565+ && (!inode_eq_iversion(inode, vdir->vd_version)
1facf9fc 32566+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
32567+ do_read = 1;
32568+ err = reinit_vdir(vdir);
32569+ if (unlikely(err))
32570+ goto out;
32571+ }
32572+
32573+ if (!do_read)
32574+ return 0; /* success */
32575+
32576+ arg.file = file;
32577+ arg.vdir = vdir;
32578+ err = au_do_read_vdir(&arg);
32579+ if (!err) {
392086de 32580+ /* file->f_pos = 0; */ /* todo: ctx->pos? */
be118d29 32581+ vdir->vd_version = inode_query_iversion(inode);
1facf9fc 32582+ vdir->vd_last.ul = 0;
32583+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32584+ if (allocated)
32585+ au_set_ivdir(inode, allocated);
32586+ } else if (allocated)
1c60b727 32587+ au_vdir_free(allocated);
1facf9fc 32588+
4f0767ce 32589+out:
1facf9fc 32590+ return err;
32591+}
32592+
32593+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
32594+{
32595+ int err, rerr;
32596+ unsigned long ul, n;
32597+ const unsigned int deblk_sz = src->vd_deblk_sz;
32598+
32599+ AuDebugOn(tgt->vd_nblk != 1);
32600+
32601+ err = -ENOMEM;
32602+ if (tgt->vd_nblk < src->vd_nblk) {
32603+ unsigned char **p;
32604+
e2f27e51
AM
32605+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
32606+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32607+ if (unlikely(!p))
32608+ goto out;
32609+ tgt->vd_deblk = p;
32610+ }
32611+
1308ab2a 32612+ if (tgt->vd_deblk_sz != deblk_sz) {
32613+ unsigned char *p;
32614+
32615+ tgt->vd_deblk_sz = deblk_sz;
e2f27e51
AM
32616+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS,
32617+ /*may_shrink*/1);
1308ab2a 32618+ if (unlikely(!p))
32619+ goto out;
32620+ tgt->vd_deblk[0] = p;
32621+ }
1facf9fc 32622+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 32623+ tgt->vd_version = src->vd_version;
32624+ tgt->vd_jiffy = src->vd_jiffy;
32625+
32626+ n = src->vd_nblk;
32627+ for (ul = 1; ul < n; ul++) {
dece6358
AM
32628+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
32629+ GFP_NOFS);
32630+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 32631+ goto out;
1308ab2a 32632+ tgt->vd_nblk++;
1facf9fc 32633+ }
1308ab2a 32634+ tgt->vd_nblk = n;
32635+ tgt->vd_last.ul = tgt->vd_last.ul;
32636+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
32637+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
32638+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 32639+ /* smp_mb(); */
32640+ return 0; /* success */
32641+
4f0767ce 32642+out:
1facf9fc 32643+ rerr = reinit_vdir(tgt);
32644+ BUG_ON(rerr);
32645+ return err;
32646+}
32647+
32648+int au_vdir_init(struct file *file)
32649+{
32650+ int err;
32651+ struct inode *inode;
32652+ struct au_vdir *vdir_cache, *allocated;
32653+
392086de 32654+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32655+ err = read_vdir(file, !file->f_pos);
32656+ if (unlikely(err))
32657+ goto out;
32658+
32659+ allocated = NULL;
32660+ vdir_cache = au_fvdir_cache(file);
32661+ if (!vdir_cache) {
1308ab2a 32662+ vdir_cache = alloc_vdir(file);
1facf9fc 32663+ err = PTR_ERR(vdir_cache);
32664+ if (IS_ERR(vdir_cache))
32665+ goto out;
32666+ allocated = vdir_cache;
32667+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
392086de 32668+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32669+ err = reinit_vdir(vdir_cache);
32670+ if (unlikely(err))
32671+ goto out;
32672+ } else
32673+ return 0; /* success */
32674+
c06a8ce3 32675+ inode = file_inode(file);
1facf9fc 32676+ err = copy_vdir(vdir_cache, au_ivdir(inode));
32677+ if (!err) {
be118d29 32678+ file->f_version = inode_query_iversion(inode);
1facf9fc 32679+ if (allocated)
32680+ au_set_fvdir_cache(file, allocated);
32681+ } else if (allocated)
1c60b727 32682+ au_vdir_free(allocated);
1facf9fc 32683+
4f0767ce 32684+out:
1facf9fc 32685+ return err;
32686+}
32687+
32688+static loff_t calc_offset(struct au_vdir *vdir)
32689+{
32690+ loff_t offset;
32691+ union au_vdir_deblk_p p;
32692+
32693+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
32694+ offset = vdir->vd_last.p.deblk - p.deblk;
32695+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
32696+ return offset;
32697+}
32698+
32699+/* returns true or false */
392086de 32700+static int seek_vdir(struct file *file, struct dir_context *ctx)
1facf9fc 32701+{
32702+ int valid;
32703+ unsigned int deblk_sz;
32704+ unsigned long ul, n;
32705+ loff_t offset;
32706+ union au_vdir_deblk_p p, deblk_end;
32707+ struct au_vdir *vdir_cache;
32708+
32709+ valid = 1;
32710+ vdir_cache = au_fvdir_cache(file);
32711+ offset = calc_offset(vdir_cache);
32712+ AuDbg("offset %lld\n", offset);
392086de 32713+ if (ctx->pos == offset)
1facf9fc 32714+ goto out;
32715+
32716+ vdir_cache->vd_last.ul = 0;
32717+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
392086de 32718+ if (!ctx->pos)
1facf9fc 32719+ goto out;
32720+
32721+ valid = 0;
32722+ deblk_sz = vdir_cache->vd_deblk_sz;
392086de 32723+ ul = div64_u64(ctx->pos, deblk_sz);
1facf9fc 32724+ AuDbg("ul %lu\n", ul);
32725+ if (ul >= vdir_cache->vd_nblk)
32726+ goto out;
32727+
32728+ n = vdir_cache->vd_nblk;
32729+ for (; ul < n; ul++) {
32730+ p.deblk = vdir_cache->vd_deblk[ul];
32731+ deblk_end.deblk = p.deblk + deblk_sz;
32732+ offset = ul;
32733+ offset *= deblk_sz;
392086de 32734+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) {
1facf9fc 32735+ unsigned int l;
32736+
32737+ l = calc_size(p.de->de_str.len);
32738+ offset += l;
32739+ p.deblk += l;
32740+ }
32741+ if (!is_deblk_end(&p, &deblk_end)) {
32742+ valid = 1;
32743+ vdir_cache->vd_last.ul = ul;
32744+ vdir_cache->vd_last.p = p;
32745+ break;
32746+ }
32747+ }
32748+
4f0767ce 32749+out:
1facf9fc 32750+ /* smp_mb(); */
b00004a5
AM
32751+ if (!valid)
32752+ AuDbg("valid %d\n", !valid);
1facf9fc 32753+ return valid;
32754+}
32755+
392086de 32756+int au_vdir_fill_de(struct file *file, struct dir_context *ctx)
1facf9fc 32757+{
1facf9fc 32758+ unsigned int l, deblk_sz;
32759+ union au_vdir_deblk_p deblk_end;
32760+ struct au_vdir *vdir_cache;
32761+ struct au_vdir_de *de;
32762+
392086de 32763+ if (!seek_vdir(file, ctx))
1facf9fc 32764+ return 0;
32765+
acd2b654 32766+ vdir_cache = au_fvdir_cache(file);
1facf9fc 32767+ deblk_sz = vdir_cache->vd_deblk_sz;
32768+ while (1) {
32769+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
32770+ deblk_end.deblk += deblk_sz;
32771+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
32772+ de = vdir_cache->vd_last.p.de;
32773+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
392086de 32774+ de->de_str.len, de->de_str.name, ctx->pos,
1facf9fc 32775+ (unsigned long)de->de_ino, de->de_type);
392086de
AM
32776+ if (unlikely(!dir_emit(ctx, de->de_str.name,
32777+ de->de_str.len, de->de_ino,
32778+ de->de_type))) {
1facf9fc 32779+ /* todo: ignore the error caused by udba? */
32780+ /* return err; */
32781+ return 0;
32782+ }
32783+
32784+ l = calc_size(de->de_str.len);
32785+ vdir_cache->vd_last.p.deblk += l;
392086de 32786+ ctx->pos += l;
1facf9fc 32787+ }
32788+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
32789+ vdir_cache->vd_last.ul++;
32790+ vdir_cache->vd_last.p.deblk
32791+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
392086de 32792+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul;
1facf9fc 32793+ continue;
32794+ }
32795+ break;
32796+ }
32797+
32798+ /* smp_mb(); */
32799+ return 0;
32800+}
7f207e10 32801diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
eca34b5c
AM
32802--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
32803+++ linux/fs/aufs/vfsub.c 2019-07-11 15:42:14.475571481 +0200
acd2b654 32804@@ -0,0 +1,902 @@
cd7a4cd9 32805+// SPDX-License-Identifier: GPL-2.0
1facf9fc 32806+/*
ba1aed25 32807+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 32808+ *
32809+ * This program, aufs is free software; you can redistribute it and/or modify
32810+ * it under the terms of the GNU General Public License as published by
32811+ * the Free Software Foundation; either version 2 of the License, or
32812+ * (at your option) any later version.
dece6358
AM
32813+ *
32814+ * This program is distributed in the hope that it will be useful,
32815+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
32816+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32817+ * GNU General Public License for more details.
32818+ *
32819+ * You should have received a copy of the GNU General Public License
523b37e3 32820+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 32821+ */
32822+
32823+/*
32824+ * sub-routines for VFS
32825+ */
32826+
8b6a4947 32827+#include <linux/mnt_namespace.h>
dece6358 32828+#include <linux/namei.h>
8cdd5066 32829+#include <linux/nsproxy.h>
dece6358
AM
32830+#include <linux/security.h>
32831+#include <linux/splice.h>
1facf9fc 32832+#include "aufs.h"
32833+
8cdd5066
JR
32834+#ifdef CONFIG_AUFS_BR_FUSE
32835+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb)
32836+{
8cdd5066
JR
32837+ if (!au_test_fuse(h_sb) || !au_userns)
32838+ return 0;
32839+
8b6a4947 32840+ return is_current_mnt_ns(mnt) ? 0 : -EACCES;
8cdd5066
JR
32841+}
32842+#endif
32843+
a2654f78
AM
32844+int vfsub_sync_filesystem(struct super_block *h_sb, int wait)
32845+{
32846+ int err;
32847+
32848+ lockdep_off();
32849+ down_read(&h_sb->s_umount);
32850+ err = __sync_filesystem(h_sb, wait);
32851+ up_read(&h_sb->s_umount);
32852+ lockdep_on();
32853+
32854+ return err;
32855+}
32856+
8cdd5066
JR
32857+/* ---------------------------------------------------------------------- */
32858+
1facf9fc 32859+int vfsub_update_h_iattr(struct path *h_path, int *did)
32860+{
32861+ int err;
32862+ struct kstat st;
32863+ struct super_block *h_sb;
32864+
32865+ /* for remote fs, leave work for its getattr or d_revalidate */
32866+ /* for bad i_attr fs, handle them in aufs_getattr() */
32867+ /* still some fs may acquire i_mutex. we need to skip them */
32868+ err = 0;
32869+ if (!did)
32870+ did = &err;
32871+ h_sb = h_path->dentry->d_sb;
32872+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
32873+ if (*did)
521ced18 32874+ err = vfsub_getattr(h_path, &st);
1facf9fc 32875+
32876+ return err;
32877+}
32878+
32879+/* ---------------------------------------------------------------------- */
32880+
4a4d8108 32881+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 32882+{
32883+ struct file *file;
32884+
b4510431 32885+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */,
7f207e10 32886+ current_cred());
2cbb1c4b
JR
32887+ if (!IS_ERR_OR_NULL(file)
32888+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
5527c038 32889+ i_readcount_inc(d_inode(path->dentry));
4a4d8108 32890+
1308ab2a 32891+ return file;
32892+}
32893+
1facf9fc 32894+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
32895+{
32896+ struct file *file;
32897+
2cbb1c4b 32898+ lockdep_off();
7f207e10 32899+ file = filp_open(path,
2cbb1c4b 32900+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 32901+ mode);
2cbb1c4b 32902+ lockdep_on();
1facf9fc 32903+ if (IS_ERR(file))
32904+ goto out;
32905+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
32906+
4f0767ce 32907+out:
1facf9fc 32908+ return file;
32909+}
32910+
b912730e
AM
32911+/*
32912+ * Ideally this function should call VFS:do_last() in order to keep all its
32913+ * checkings. But it is very hard for aufs to regenerate several VFS internal
32914+ * structure such as nameidata. This is a second (or third) best approach.
32915+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open().
32916+ */
32917+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 32918+ struct vfsub_aopen_args *args)
b912730e
AM
32919+{
32920+ int err;
acd2b654 32921+ struct au_branch *br = args->br;
b912730e
AM
32922+ struct file *file = args->file;
32923+ /* copied from linux/fs/namei.c:atomic_open() */
32924+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL;
32925+
32926+ IMustLock(dir);
32927+ AuDebugOn(!dir->i_op->atomic_open);
32928+
32929+ err = au_br_test_oflag(args->open_flag, br);
32930+ if (unlikely(err))
32931+ goto out;
32932+
acd2b654
AM
32933+ au_lcnt_inc(&br->br_nfiles);
32934+ file->f_path.dentry = DENTRY_NOT_SET;
32935+ file->f_path.mnt = au_br_mnt(br);
32936+ AuDbg("%ps\n", dir->i_op->atomic_open);
b912730e 32937+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag,
acd2b654
AM
32938+ args->create_mode);
32939+ if (unlikely(err < 0)) {
32940+ au_lcnt_dec(&br->br_nfiles);
b912730e 32941+ goto out;
acd2b654 32942+ }
b912730e 32943+
acd2b654
AM
32944+ /* temporary workaround for nfsv4 branch */
32945+ if (au_test_nfs(dir->i_sb))
32946+ nfs_mark_for_revalidate(dir);
b912730e 32947+
acd2b654
AM
32948+ if (file->f_mode & FMODE_CREATED)
32949+ fsnotify_create(dir, dentry);
32950+ if (!(file->f_mode & FMODE_OPENED)) {
32951+ au_lcnt_dec(&br->br_nfiles);
32952+ goto out;
b912730e
AM
32953+ }
32954+
acd2b654
AM
32955+ /* todo: call VFS:may_open() here */
32956+ /* todo: ima_file_check() too? */
32957+ if (!err && (args->open_flag & __FMODE_EXEC))
32958+ err = deny_write_access(file);
32959+ if (!err)
32960+ fsnotify_open(file);
32961+ else
32962+ au_lcnt_dec(&br->br_nfiles);
32963+ /* note that the file is created and still opened */
b912730e
AM
32964+
32965+out:
32966+ return err;
32967+}
32968+
1facf9fc 32969+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
32970+{
32971+ int err;
32972+
1facf9fc 32973+ err = kern_path(name, flags, path);
5527c038 32974+ if (!err && d_is_positive(path->dentry))
1facf9fc 32975+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
32976+ return err;
32977+}
32978+
febd17d6
JR
32979+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
32980+ struct dentry *parent, int len)
32981+{
32982+ struct path path = {
32983+ .mnt = NULL
32984+ };
32985+
32986+ path.dentry = lookup_one_len_unlocked(name, parent, len);
32987+ if (IS_ERR(path.dentry))
32988+ goto out;
32989+ if (d_is_positive(path.dentry))
32990+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
32991+
32992+out:
32993+ AuTraceErrPtr(path.dentry);
32994+ return path.dentry;
32995+}
32996+
1facf9fc 32997+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
32998+ int len)
32999+{
33000+ struct path path = {
33001+ .mnt = NULL
33002+ };
33003+
1308ab2a 33004+ /* VFS checks it too, but by WARN_ON_ONCE() */
5527c038 33005+ IMustLock(d_inode(parent));
1facf9fc 33006+
33007+ path.dentry = lookup_one_len(name, parent, len);
33008+ if (IS_ERR(path.dentry))
33009+ goto out;
5527c038 33010+ if (d_is_positive(path.dentry))
1facf9fc 33011+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
33012+
4f0767ce 33013+out:
4a4d8108 33014+ AuTraceErrPtr(path.dentry);
1facf9fc 33015+ return path.dentry;
33016+}
33017+
b4510431 33018+void vfsub_call_lkup_one(void *args)
2cbb1c4b 33019+{
b4510431
AM
33020+ struct vfsub_lkup_one_args *a = args;
33021+ *a->errp = vfsub_lkup_one(a->name, a->parent);
2cbb1c4b
JR
33022+}
33023+
1facf9fc 33024+/* ---------------------------------------------------------------------- */
33025+
33026+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
33027+ struct dentry *d2, struct au_hinode *hdir2)
33028+{
33029+ struct dentry *d;
33030+
2cbb1c4b 33031+ lockdep_off();
1facf9fc 33032+ d = lock_rename(d1, d2);
2cbb1c4b 33033+ lockdep_on();
4a4d8108 33034+ au_hn_suspend(hdir1);
1facf9fc 33035+ if (hdir1 != hdir2)
4a4d8108 33036+ au_hn_suspend(hdir2);
1facf9fc 33037+
33038+ return d;
33039+}
33040+
33041+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
33042+ struct dentry *d2, struct au_hinode *hdir2)
33043+{
4a4d8108 33044+ au_hn_resume(hdir1);
1facf9fc 33045+ if (hdir1 != hdir2)
4a4d8108 33046+ au_hn_resume(hdir2);
2cbb1c4b 33047+ lockdep_off();
1facf9fc 33048+ unlock_rename(d1, d2);
2cbb1c4b 33049+ lockdep_on();
1facf9fc 33050+}
33051+
33052+/* ---------------------------------------------------------------------- */
33053+
b4510431 33054+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
1facf9fc 33055+{
33056+ int err;
33057+ struct dentry *d;
33058+
33059+ IMustLock(dir);
33060+
33061+ d = path->dentry;
33062+ path->dentry = d->d_parent;
b752ccd1 33063+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 33064+ path->dentry = d;
33065+ if (unlikely(err))
33066+ goto out;
33067+
c1595e42 33068+ lockdep_off();
b4510431 33069+ err = vfs_create(dir, path->dentry, mode, want_excl);
c1595e42 33070+ lockdep_on();
1facf9fc 33071+ if (!err) {
33072+ struct path tmp = *path;
33073+ int did;
33074+
33075+ vfsub_update_h_iattr(&tmp, &did);
33076+ if (did) {
33077+ tmp.dentry = path->dentry->d_parent;
33078+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33079+ }
33080+ /*ignore*/
33081+ }
33082+
4f0767ce 33083+out:
1facf9fc 33084+ return err;
33085+}
33086+
33087+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
33088+{
33089+ int err;
33090+ struct dentry *d;
33091+
33092+ IMustLock(dir);
33093+
33094+ d = path->dentry;
33095+ path->dentry = d->d_parent;
b752ccd1 33096+ err = security_path_symlink(path, d, symname);
1facf9fc 33097+ path->dentry = d;
33098+ if (unlikely(err))
33099+ goto out;
33100+
c1595e42 33101+ lockdep_off();
1facf9fc 33102+ err = vfs_symlink(dir, path->dentry, symname);
c1595e42 33103+ lockdep_on();
1facf9fc 33104+ if (!err) {
33105+ struct path tmp = *path;
33106+ int did;
33107+
33108+ vfsub_update_h_iattr(&tmp, &did);
33109+ if (did) {
33110+ tmp.dentry = path->dentry->d_parent;
33111+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33112+ }
33113+ /*ignore*/
33114+ }
33115+
4f0767ce 33116+out:
1facf9fc 33117+ return err;
33118+}
33119+
33120+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
33121+{
33122+ int err;
33123+ struct dentry *d;
33124+
33125+ IMustLock(dir);
33126+
33127+ d = path->dentry;
33128+ path->dentry = d->d_parent;
027c5e7a 33129+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 33130+ path->dentry = d;
33131+ if (unlikely(err))
33132+ goto out;
33133+
c1595e42 33134+ lockdep_off();
1facf9fc 33135+ err = vfs_mknod(dir, path->dentry, mode, dev);
c1595e42 33136+ lockdep_on();
1facf9fc 33137+ if (!err) {
33138+ struct path tmp = *path;
33139+ int did;
33140+
33141+ vfsub_update_h_iattr(&tmp, &did);
33142+ if (did) {
33143+ tmp.dentry = path->dentry->d_parent;
33144+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33145+ }
33146+ /*ignore*/
33147+ }
33148+
4f0767ce 33149+out:
1facf9fc 33150+ return err;
33151+}
33152+
33153+static int au_test_nlink(struct inode *inode)
33154+{
33155+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
33156+
33157+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
33158+ || inode->i_nlink < link_max)
33159+ return 0;
33160+ return -EMLINK;
33161+}
33162+
523b37e3
AM
33163+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
33164+ struct inode **delegated_inode)
1facf9fc 33165+{
33166+ int err;
33167+ struct dentry *d;
33168+
33169+ IMustLock(dir);
33170+
5527c038 33171+ err = au_test_nlink(d_inode(src_dentry));
1facf9fc 33172+ if (unlikely(err))
33173+ return err;
33174+
b4510431 33175+ /* we don't call may_linkat() */
1facf9fc 33176+ d = path->dentry;
33177+ path->dentry = d->d_parent;
b752ccd1 33178+ err = security_path_link(src_dentry, path, d);
1facf9fc 33179+ path->dentry = d;
33180+ if (unlikely(err))
33181+ goto out;
33182+
2cbb1c4b 33183+ lockdep_off();
523b37e3 33184+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode);
2cbb1c4b 33185+ lockdep_on();
1facf9fc 33186+ if (!err) {
33187+ struct path tmp = *path;
33188+ int did;
33189+
33190+ /* fuse has different memory inode for the same inumber */
33191+ vfsub_update_h_iattr(&tmp, &did);
33192+ if (did) {
33193+ tmp.dentry = path->dentry->d_parent;
33194+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33195+ tmp.dentry = src_dentry;
33196+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33197+ }
33198+ /*ignore*/
33199+ }
33200+
4f0767ce 33201+out:
1facf9fc 33202+ return err;
33203+}
33204+
33205+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
523b37e3 33206+ struct inode *dir, struct path *path,
f2c43d5f 33207+ struct inode **delegated_inode, unsigned int flags)
1facf9fc 33208+{
33209+ int err;
33210+ struct path tmp = {
33211+ .mnt = path->mnt
33212+ };
33213+ struct dentry *d;
33214+
33215+ IMustLock(dir);
33216+ IMustLock(src_dir);
33217+
33218+ d = path->dentry;
33219+ path->dentry = d->d_parent;
33220+ tmp.dentry = src_dentry->d_parent;
38d290e6 33221+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0);
1facf9fc 33222+ path->dentry = d;
33223+ if (unlikely(err))
33224+ goto out;
33225+
2cbb1c4b 33226+ lockdep_off();
523b37e3 33227+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry,
f2c43d5f 33228+ delegated_inode, flags);
2cbb1c4b 33229+ lockdep_on();
1facf9fc 33230+ if (!err) {
33231+ int did;
33232+
33233+ tmp.dentry = d->d_parent;
33234+ vfsub_update_h_iattr(&tmp, &did);
33235+ if (did) {
33236+ tmp.dentry = src_dentry;
33237+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33238+ tmp.dentry = src_dentry->d_parent;
33239+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33240+ }
33241+ /*ignore*/
33242+ }
33243+
4f0767ce 33244+out:
1facf9fc 33245+ return err;
33246+}
33247+
33248+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
33249+{
33250+ int err;
33251+ struct dentry *d;
33252+
33253+ IMustLock(dir);
33254+
33255+ d = path->dentry;
33256+ path->dentry = d->d_parent;
b752ccd1 33257+ err = security_path_mkdir(path, d, mode);
1facf9fc 33258+ path->dentry = d;
33259+ if (unlikely(err))
33260+ goto out;
33261+
c1595e42 33262+ lockdep_off();
1facf9fc 33263+ err = vfs_mkdir(dir, path->dentry, mode);
c1595e42 33264+ lockdep_on();
1facf9fc 33265+ if (!err) {
33266+ struct path tmp = *path;
33267+ int did;
33268+
33269+ vfsub_update_h_iattr(&tmp, &did);
33270+ if (did) {
33271+ tmp.dentry = path->dentry->d_parent;
33272+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33273+ }
33274+ /*ignore*/
33275+ }
33276+
4f0767ce 33277+out:
1facf9fc 33278+ return err;
33279+}
33280+
33281+int vfsub_rmdir(struct inode *dir, struct path *path)
33282+{
33283+ int err;
33284+ struct dentry *d;
33285+
33286+ IMustLock(dir);
33287+
33288+ d = path->dentry;
33289+ path->dentry = d->d_parent;
b752ccd1 33290+ err = security_path_rmdir(path, d);
1facf9fc 33291+ path->dentry = d;
33292+ if (unlikely(err))
33293+ goto out;
33294+
2cbb1c4b 33295+ lockdep_off();
1facf9fc 33296+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 33297+ lockdep_on();
1facf9fc 33298+ if (!err) {
33299+ struct path tmp = {
33300+ .dentry = path->dentry->d_parent,
33301+ .mnt = path->mnt
33302+ };
33303+
33304+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33305+ }
33306+
4f0767ce 33307+out:
1facf9fc 33308+ return err;
33309+}
33310+
33311+/* ---------------------------------------------------------------------- */
33312+
9dbd164d 33313+/* todo: support mmap_sem? */
1facf9fc 33314+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33315+ loff_t *ppos)
33316+{
33317+ ssize_t err;
33318+
2cbb1c4b 33319+ lockdep_off();
1facf9fc 33320+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 33321+ lockdep_on();
1facf9fc 33322+ if (err >= 0)
33323+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33324+ return err;
33325+}
33326+
33327+/* todo: kernel_read()? */
33328+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33329+ loff_t *ppos)
33330+{
33331+ ssize_t err;
33332+ mm_segment_t oldfs;
b752ccd1
AM
33333+ union {
33334+ void *k;
33335+ char __user *u;
33336+ } buf;
1facf9fc 33337+
b752ccd1 33338+ buf.k = kbuf;
1facf9fc 33339+ oldfs = get_fs();
33340+ set_fs(KERNEL_DS);
b752ccd1 33341+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 33342+ set_fs(oldfs);
33343+ return err;
33344+}
33345+
33346+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33347+ loff_t *ppos)
33348+{
33349+ ssize_t err;
33350+
2cbb1c4b 33351+ lockdep_off();
1facf9fc 33352+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 33353+ lockdep_on();
1facf9fc 33354+ if (err >= 0)
33355+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33356+ return err;
33357+}
33358+
33359+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
33360+{
33361+ ssize_t err;
33362+ mm_segment_t oldfs;
b752ccd1
AM
33363+ union {
33364+ void *k;
33365+ const char __user *u;
33366+ } buf;
1facf9fc 33367+
b752ccd1 33368+ buf.k = kbuf;
1facf9fc 33369+ oldfs = get_fs();
33370+ set_fs(KERNEL_DS);
b752ccd1 33371+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 33372+ set_fs(oldfs);
33373+ return err;
33374+}
33375+
4a4d8108
AM
33376+int vfsub_flush(struct file *file, fl_owner_t id)
33377+{
33378+ int err;
33379+
33380+ err = 0;
523b37e3 33381+ if (file->f_op->flush) {
2000de60 33382+ if (!au_test_nfs(file->f_path.dentry->d_sb))
2cbb1c4b
JR
33383+ err = file->f_op->flush(file, id);
33384+ else {
33385+ lockdep_off();
33386+ err = file->f_op->flush(file, id);
33387+ lockdep_on();
33388+ }
4a4d8108
AM
33389+ if (!err)
33390+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
33391+ /*ignore*/
33392+ }
33393+ return err;
33394+}
33395+
392086de 33396+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx)
1facf9fc 33397+{
33398+ int err;
33399+
062440b3 33400+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 33401+
2cbb1c4b 33402+ lockdep_off();
392086de 33403+ err = iterate_dir(file, ctx);
2cbb1c4b 33404+ lockdep_on();
1facf9fc 33405+ if (err >= 0)
33406+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1c60b727 33407+
1facf9fc 33408+ return err;
33409+}
33410+
33411+long vfsub_splice_to(struct file *in, loff_t *ppos,
33412+ struct pipe_inode_info *pipe, size_t len,
33413+ unsigned int flags)
33414+{
33415+ long err;
33416+
2cbb1c4b 33417+ lockdep_off();
0fc653ad 33418+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 33419+ lockdep_on();
4a4d8108 33420+ file_accessed(in);
1facf9fc 33421+ if (err >= 0)
33422+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
33423+ return err;
33424+}
33425+
33426+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33427+ loff_t *ppos, size_t len, unsigned int flags)
33428+{
33429+ long err;
33430+
2cbb1c4b 33431+ lockdep_off();
0fc653ad 33432+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 33433+ lockdep_on();
1facf9fc 33434+ if (err >= 0)
33435+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
33436+ return err;
33437+}
33438+
53392da6
AM
33439+int vfsub_fsync(struct file *file, struct path *path, int datasync)
33440+{
33441+ int err;
33442+
33443+ /* file can be NULL */
33444+ lockdep_off();
33445+ err = vfs_fsync(file, datasync);
33446+ lockdep_on();
33447+ if (!err) {
33448+ if (!path) {
33449+ AuDebugOn(!file);
33450+ path = &file->f_path;
33451+ }
33452+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
33453+ }
33454+ return err;
33455+}
33456+
1facf9fc 33457+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
33458+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33459+ struct file *h_file)
33460+{
33461+ int err;
33462+ struct inode *h_inode;
c06a8ce3 33463+ struct super_block *h_sb;
1facf9fc 33464+
1facf9fc 33465+ if (!h_file) {
c06a8ce3
AM
33466+ err = vfsub_truncate(h_path, length);
33467+ goto out;
1facf9fc 33468+ }
33469+
5527c038 33470+ h_inode = d_inode(h_path->dentry);
c06a8ce3
AM
33471+ h_sb = h_inode->i_sb;
33472+ lockdep_off();
33473+ sb_start_write(h_sb);
33474+ lockdep_on();
1facf9fc 33475+ err = locks_verify_truncate(h_inode, h_file, length);
33476+ if (!err)
953406b4 33477+ err = security_path_truncate(h_path);
2cbb1c4b
JR
33478+ if (!err) {
33479+ lockdep_off();
1facf9fc 33480+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
33481+ lockdep_on();
33482+ }
c06a8ce3
AM
33483+ lockdep_off();
33484+ sb_end_write(h_sb);
33485+ lockdep_on();
1facf9fc 33486+
4f0767ce 33487+out:
1facf9fc 33488+ return err;
33489+}
33490+
33491+/* ---------------------------------------------------------------------- */
33492+
33493+struct au_vfsub_mkdir_args {
33494+ int *errp;
33495+ struct inode *dir;
33496+ struct path *path;
33497+ int mode;
33498+};
33499+
33500+static void au_call_vfsub_mkdir(void *args)
33501+{
33502+ struct au_vfsub_mkdir_args *a = args;
33503+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
33504+}
33505+
33506+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
33507+{
33508+ int err, do_sio, wkq_err;
33509+
33510+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33511+ if (!do_sio) {
33512+ lockdep_off();
1facf9fc 33513+ err = vfsub_mkdir(dir, path, mode);
c1595e42
JR
33514+ lockdep_on();
33515+ } else {
1facf9fc 33516+ struct au_vfsub_mkdir_args args = {
33517+ .errp = &err,
33518+ .dir = dir,
33519+ .path = path,
33520+ .mode = mode
33521+ };
33522+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
33523+ if (unlikely(wkq_err))
33524+ err = wkq_err;
33525+ }
33526+
33527+ return err;
33528+}
33529+
33530+struct au_vfsub_rmdir_args {
33531+ int *errp;
33532+ struct inode *dir;
33533+ struct path *path;
33534+};
33535+
33536+static void au_call_vfsub_rmdir(void *args)
33537+{
33538+ struct au_vfsub_rmdir_args *a = args;
33539+ *a->errp = vfsub_rmdir(a->dir, a->path);
33540+}
33541+
33542+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
33543+{
33544+ int err, do_sio, wkq_err;
33545+
33546+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33547+ if (!do_sio) {
33548+ lockdep_off();
1facf9fc 33549+ err = vfsub_rmdir(dir, path);
c1595e42
JR
33550+ lockdep_on();
33551+ } else {
1facf9fc 33552+ struct au_vfsub_rmdir_args args = {
33553+ .errp = &err,
33554+ .dir = dir,
33555+ .path = path
33556+ };
33557+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
33558+ if (unlikely(wkq_err))
33559+ err = wkq_err;
33560+ }
33561+
33562+ return err;
33563+}
33564+
33565+/* ---------------------------------------------------------------------- */
33566+
33567+struct notify_change_args {
33568+ int *errp;
33569+ struct path *path;
33570+ struct iattr *ia;
523b37e3 33571+ struct inode **delegated_inode;
1facf9fc 33572+};
33573+
33574+static void call_notify_change(void *args)
33575+{
33576+ struct notify_change_args *a = args;
33577+ struct inode *h_inode;
33578+
5527c038 33579+ h_inode = d_inode(a->path->dentry);
1facf9fc 33580+ IMustLock(h_inode);
33581+
33582+ *a->errp = -EPERM;
33583+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
c1595e42 33584+ lockdep_off();
523b37e3
AM
33585+ *a->errp = notify_change(a->path->dentry, a->ia,
33586+ a->delegated_inode);
c1595e42 33587+ lockdep_on();
1facf9fc 33588+ if (!*a->errp)
33589+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
33590+ }
33591+ AuTraceErr(*a->errp);
33592+}
33593+
523b37e3
AM
33594+int vfsub_notify_change(struct path *path, struct iattr *ia,
33595+ struct inode **delegated_inode)
1facf9fc 33596+{
33597+ int err;
33598+ struct notify_change_args args = {
523b37e3
AM
33599+ .errp = &err,
33600+ .path = path,
33601+ .ia = ia,
33602+ .delegated_inode = delegated_inode
1facf9fc 33603+ };
33604+
33605+ call_notify_change(&args);
33606+
33607+ return err;
33608+}
33609+
523b37e3
AM
33610+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
33611+ struct inode **delegated_inode)
1facf9fc 33612+{
33613+ int err, wkq_err;
33614+ struct notify_change_args args = {
523b37e3
AM
33615+ .errp = &err,
33616+ .path = path,
33617+ .ia = ia,
33618+ .delegated_inode = delegated_inode
1facf9fc 33619+ };
33620+
33621+ wkq_err = au_wkq_wait(call_notify_change, &args);
33622+ if (unlikely(wkq_err))
33623+ err = wkq_err;
33624+
33625+ return err;
33626+}
33627+
33628+/* ---------------------------------------------------------------------- */
33629+
33630+struct unlink_args {
33631+ int *errp;
33632+ struct inode *dir;
33633+ struct path *path;
523b37e3 33634+ struct inode **delegated_inode;
1facf9fc 33635+};
33636+
33637+static void call_unlink(void *args)
33638+{
33639+ struct unlink_args *a = args;
33640+ struct dentry *d = a->path->dentry;
33641+ struct inode *h_inode;
33642+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
c1595e42 33643+ && au_dcount(d) == 1);
1facf9fc 33644+
33645+ IMustLock(a->dir);
33646+
33647+ a->path->dentry = d->d_parent;
33648+ *a->errp = security_path_unlink(a->path, d);
33649+ a->path->dentry = d;
33650+ if (unlikely(*a->errp))
33651+ return;
33652+
33653+ if (!stop_sillyrename)
33654+ dget(d);
5527c038
JR
33655+ h_inode = NULL;
33656+ if (d_is_positive(d)) {
33657+ h_inode = d_inode(d);
027c5e7a 33658+ ihold(h_inode);
5527c038 33659+ }
1facf9fc 33660+
2cbb1c4b 33661+ lockdep_off();
523b37e3 33662+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode);
2cbb1c4b 33663+ lockdep_on();
1facf9fc 33664+ if (!*a->errp) {
33665+ struct path tmp = {
33666+ .dentry = d->d_parent,
33667+ .mnt = a->path->mnt
33668+ };
33669+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33670+ }
33671+
33672+ if (!stop_sillyrename)
33673+ dput(d);
33674+ if (h_inode)
33675+ iput(h_inode);
33676+
33677+ AuTraceErr(*a->errp);
33678+}
33679+
33680+/*
33681+ * @dir: must be locked.
33682+ * @dentry: target dentry.
33683+ */
523b37e3
AM
33684+int vfsub_unlink(struct inode *dir, struct path *path,
33685+ struct inode **delegated_inode, int force)
1facf9fc 33686+{
33687+ int err;
33688+ struct unlink_args args = {
523b37e3
AM
33689+ .errp = &err,
33690+ .dir = dir,
33691+ .path = path,
33692+ .delegated_inode = delegated_inode
1facf9fc 33693+ };
33694+
33695+ if (!force)
33696+ call_unlink(&args);
33697+ else {
33698+ int wkq_err;
33699+
33700+ wkq_err = au_wkq_wait(call_unlink, &args);
33701+ if (unlikely(wkq_err))
33702+ err = wkq_err;
33703+ }
33704+
33705+ return err;
33706+}
7f207e10 33707diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
eca34b5c
AM
33708--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
33709+++ linux/fs/aufs/vfsub.h 2019-07-11 15:42:14.475571481 +0200
eca801bf 33710@@ -0,0 +1,354 @@
062440b3 33711+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 33712+/*
ba1aed25 33713+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 33714+ *
33715+ * This program, aufs is free software; you can redistribute it and/or modify
33716+ * it under the terms of the GNU General Public License as published by
33717+ * the Free Software Foundation; either version 2 of the License, or
33718+ * (at your option) any later version.
dece6358
AM
33719+ *
33720+ * This program is distributed in the hope that it will be useful,
33721+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33722+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33723+ * GNU General Public License for more details.
33724+ *
33725+ * You should have received a copy of the GNU General Public License
523b37e3 33726+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 33727+ */
33728+
33729+/*
33730+ * sub-routines for VFS
33731+ */
33732+
33733+#ifndef __AUFS_VFSUB_H__
33734+#define __AUFS_VFSUB_H__
33735+
33736+#ifdef __KERNEL__
33737+
33738+#include <linux/fs.h>
b4510431 33739+#include <linux/mount.h>
8cdd5066 33740+#include <linux/posix_acl.h>
c1595e42 33741+#include <linux/xattr.h>
7f207e10 33742+#include "debug.h"
1facf9fc 33743+
7f207e10 33744+/* copied from linux/fs/internal.h */
2cbb1c4b 33745+/* todo: BAD approach!! */
c06a8ce3 33746+extern void __mnt_drop_write(struct vfsmount *);
acd2b654 33747+extern struct file *alloc_empty_file(int, const struct cred *);
7f207e10
AM
33748+
33749+/* ---------------------------------------------------------------------- */
1facf9fc 33750+
33751+/* lock subclass for lower inode */
33752+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
33753+/* reduce? gave up. */
33754+enum {
c1595e42 33755+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */
1facf9fc 33756+ AuLsc_I_PARENT, /* lower inode, parent first */
33757+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 33758+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 33759+ AuLsc_I_CHILD,
33760+ AuLsc_I_CHILD2,
33761+ AuLsc_I_End
33762+};
33763+
33764+/* to debug easier, do not make them inlined functions */
33765+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
febd17d6 33766+#define IMustLock(i) AuDebugOn(!inode_is_locked(i))
1facf9fc 33767+
33768+/* ---------------------------------------------------------------------- */
33769+
7f207e10
AM
33770+static inline void vfsub_drop_nlink(struct inode *inode)
33771+{
33772+ AuDebugOn(!inode->i_nlink);
33773+ drop_nlink(inode);
33774+}
33775+
027c5e7a
AM
33776+static inline void vfsub_dead_dir(struct inode *inode)
33777+{
33778+ AuDebugOn(!S_ISDIR(inode->i_mode));
33779+ inode->i_flags |= S_DEAD;
33780+ clear_nlink(inode);
33781+}
33782+
392086de
AM
33783+static inline int vfsub_native_ro(struct inode *inode)
33784+{
8b6a4947 33785+ return sb_rdonly(inode->i_sb)
392086de
AM
33786+ || IS_RDONLY(inode)
33787+ /* || IS_APPEND(inode) */
33788+ || IS_IMMUTABLE(inode);
33789+}
33790+
8cdd5066
JR
33791+#ifdef CONFIG_AUFS_BR_FUSE
33792+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb);
33793+#else
33794+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb);
33795+#endif
33796+
a2654f78
AM
33797+int vfsub_sync_filesystem(struct super_block *h_sb, int wait);
33798+
7f207e10
AM
33799+/* ---------------------------------------------------------------------- */
33800+
33801+int vfsub_update_h_iattr(struct path *h_path, int *did);
33802+struct file *vfsub_dentry_open(struct path *path, int flags);
33803+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
acd2b654 33804+struct au_branch;
b912730e 33805+struct vfsub_aopen_args {
acd2b654
AM
33806+ struct file *file;
33807+ unsigned int open_flag;
33808+ umode_t create_mode;
33809+ struct au_branch *br;
b912730e 33810+};
b912730e 33811+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 33812+ struct vfsub_aopen_args *args);
1facf9fc 33813+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
b4510431 33814+
febd17d6
JR
33815+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
33816+ struct dentry *parent, int len);
1facf9fc 33817+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
33818+ int len);
b4510431
AM
33819+
33820+struct vfsub_lkup_one_args {
33821+ struct dentry **errp;
33822+ struct qstr *name;
33823+ struct dentry *parent;
33824+};
33825+
33826+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
33827+ struct dentry *parent)
33828+{
33829+ return vfsub_lookup_one_len(name->name, parent, name->len);
33830+}
33831+
33832+void vfsub_call_lkup_one(void *args);
33833+
33834+/* ---------------------------------------------------------------------- */
33835+
33836+static inline int vfsub_mnt_want_write(struct vfsmount *mnt)
33837+{
33838+ int err;
076b876e 33839+
b4510431
AM
33840+ lockdep_off();
33841+ err = mnt_want_write(mnt);
33842+ lockdep_on();
33843+ return err;
33844+}
33845+
33846+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
33847+{
33848+ lockdep_off();
33849+ mnt_drop_write(mnt);
33850+ lockdep_on();
33851+}
1facf9fc 33852+
7e9cd9fe 33853+#if 0 /* reserved */
c06a8ce3
AM
33854+static inline void vfsub_mnt_drop_write_file(struct file *file)
33855+{
33856+ lockdep_off();
33857+ mnt_drop_write_file(file);
33858+ lockdep_on();
33859+}
7e9cd9fe 33860+#endif
c06a8ce3 33861+
1facf9fc 33862+/* ---------------------------------------------------------------------- */
33863+
33864+struct au_hinode;
33865+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
33866+ struct dentry *d2, struct au_hinode *hdir2);
33867+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
33868+ struct dentry *d2, struct au_hinode *hdir2);
33869+
537831f9
AM
33870+int vfsub_create(struct inode *dir, struct path *path, int mode,
33871+ bool want_excl);
1facf9fc 33872+int vfsub_symlink(struct inode *dir, struct path *path,
33873+ const char *symname);
33874+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
33875+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
523b37e3 33876+ struct path *path, struct inode **delegated_inode);
1facf9fc 33877+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
523b37e3 33878+ struct inode *hdir, struct path *path,
f2c43d5f 33879+ struct inode **delegated_inode, unsigned int flags);
1facf9fc 33880+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
33881+int vfsub_rmdir(struct inode *dir, struct path *path);
33882+
33883+/* ---------------------------------------------------------------------- */
33884+
33885+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33886+ loff_t *ppos);
33887+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33888+ loff_t *ppos);
33889+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33890+ loff_t *ppos);
33891+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
33892+ loff_t *ppos);
4a4d8108 33893+int vfsub_flush(struct file *file, fl_owner_t id);
392086de
AM
33894+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx);
33895+
c06a8ce3
AM
33896+static inline loff_t vfsub_f_size_read(struct file *file)
33897+{
33898+ return i_size_read(file_inode(file));
33899+}
33900+
4a4d8108
AM
33901+static inline unsigned int vfsub_file_flags(struct file *file)
33902+{
33903+ unsigned int flags;
33904+
33905+ spin_lock(&file->f_lock);
33906+ flags = file->f_flags;
33907+ spin_unlock(&file->f_lock);
33908+
33909+ return flags;
33910+}
1308ab2a 33911+
f0c0a007
AM
33912+static inline int vfsub_file_execed(struct file *file)
33913+{
33914+ /* todo: direct access f_flags */
33915+ return !!(vfsub_file_flags(file) & __FMODE_EXEC);
33916+}
33917+
7e9cd9fe 33918+#if 0 /* reserved */
1facf9fc 33919+static inline void vfsub_file_accessed(struct file *h_file)
33920+{
33921+ file_accessed(h_file);
33922+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
33923+}
7e9cd9fe 33924+#endif
1facf9fc 33925+
79b8bda9 33926+#if 0 /* reserved */
1facf9fc 33927+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
33928+ struct dentry *h_dentry)
33929+{
33930+ struct path h_path = {
33931+ .dentry = h_dentry,
33932+ .mnt = h_mnt
33933+ };
92d182d2 33934+ touch_atime(&h_path);
1facf9fc 33935+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
33936+}
79b8bda9 33937+#endif
1facf9fc 33938+
cd7a4cd9
AM
33939+static inline int vfsub_update_time(struct inode *h_inode,
33940+ struct timespec64 *ts, int flags)
0c3ec466 33941+{
5afbbe0d 33942+ return update_time(h_inode, ts, flags);
0c3ec466
AM
33943+ /* no vfsub_update_h_iattr() since we don't have struct path */
33944+}
33945+
8cdd5066
JR
33946+#ifdef CONFIG_FS_POSIX_ACL
33947+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode)
33948+{
33949+ int err;
33950+
33951+ err = posix_acl_chmod(h_inode, h_mode);
33952+ if (err == -EOPNOTSUPP)
33953+ err = 0;
33954+ return err;
33955+}
33956+#else
33957+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode);
33958+#endif
33959+
4a4d8108
AM
33960+long vfsub_splice_to(struct file *in, loff_t *ppos,
33961+ struct pipe_inode_info *pipe, size_t len,
33962+ unsigned int flags);
33963+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33964+ loff_t *ppos, size_t len, unsigned int flags);
c06a8ce3
AM
33965+
33966+static inline long vfsub_truncate(struct path *path, loff_t length)
33967+{
33968+ long err;
076b876e 33969+
c06a8ce3
AM
33970+ lockdep_off();
33971+ err = vfs_truncate(path, length);
33972+ lockdep_on();
33973+ return err;
33974+}
33975+
4a4d8108
AM
33976+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33977+ struct file *h_file);
53392da6 33978+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 33979+
521ced18
JR
33980+/*
33981+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such
33982+ * ioctl.
33983+ */
9f237c51
AM
33984+static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst,
33985+ loff_t len)
521ced18 33986+{
9f237c51 33987+ loff_t err;
521ced18
JR
33988+
33989+ lockdep_off();
9f237c51 33990+ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0);
521ced18
JR
33991+ lockdep_on();
33992+
33993+ return err;
33994+}
33995+
33996+/* copy_file_range(2) is a systemcall */
33997+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos,
33998+ struct file *dst, loff_t dst_pos,
33999+ size_t len, unsigned int flags)
34000+{
34001+ ssize_t ssz;
34002+
34003+ lockdep_off();
34004+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags);
34005+ lockdep_on();
34006+
34007+ return ssz;
34008+}
34009+
1facf9fc 34010+/* ---------------------------------------------------------------------- */
34011+
34012+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
34013+{
34014+ loff_t err;
34015+
2cbb1c4b 34016+ lockdep_off();
1facf9fc 34017+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 34018+ lockdep_on();
1facf9fc 34019+ return err;
34020+}
34021+
34022+/* ---------------------------------------------------------------------- */
34023+
4a4d8108
AM
34024+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
34025+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
523b37e3
AM
34026+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
34027+ struct inode **delegated_inode);
34028+int vfsub_notify_change(struct path *path, struct iattr *ia,
34029+ struct inode **delegated_inode);
34030+int vfsub_unlink(struct inode *dir, struct path *path,
34031+ struct inode **delegated_inode, int force);
4a4d8108 34032+
521ced18
JR
34033+static inline int vfsub_getattr(const struct path *path, struct kstat *st)
34034+{
34035+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
34036+}
34037+
c1595e42
JR
34038+/* ---------------------------------------------------------------------- */
34039+
34040+static inline int vfsub_setxattr(struct dentry *dentry, const char *name,
34041+ const void *value, size_t size, int flags)
34042+{
34043+ int err;
34044+
34045+ lockdep_off();
34046+ err = vfs_setxattr(dentry, name, value, size, flags);
34047+ lockdep_on();
34048+
34049+ return err;
34050+}
34051+
34052+static inline int vfsub_removexattr(struct dentry *dentry, const char *name)
34053+{
34054+ int err;
34055+
34056+ lockdep_off();
34057+ err = vfs_removexattr(dentry, name);
34058+ lockdep_on();
34059+
34060+ return err;
34061+}
34062+
1facf9fc 34063+#endif /* __KERNEL__ */
34064+#endif /* __AUFS_VFSUB_H__ */
7f207e10 34065diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
eca34b5c
AM
34066--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
34067+++ linux/fs/aufs/wbr_policy.c 2019-07-11 15:42:14.475571481 +0200
cd7a4cd9
AM
34068@@ -0,0 +1,830 @@
34069+// SPDX-License-Identifier: GPL-2.0
1facf9fc 34070+/*
ba1aed25 34071+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 34072+ *
34073+ * This program, aufs is free software; you can redistribute it and/or modify
34074+ * it under the terms of the GNU General Public License as published by
34075+ * the Free Software Foundation; either version 2 of the License, or
34076+ * (at your option) any later version.
dece6358
AM
34077+ *
34078+ * This program is distributed in the hope that it will be useful,
34079+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34080+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34081+ * GNU General Public License for more details.
34082+ *
34083+ * You should have received a copy of the GNU General Public License
523b37e3 34084+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34085+ */
34086+
34087+/*
34088+ * policies for selecting one among multiple writable branches
34089+ */
34090+
34091+#include <linux/statfs.h>
34092+#include "aufs.h"
34093+
34094+/* subset of cpup_attr() */
34095+static noinline_for_stack
34096+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
34097+{
34098+ int err, sbits;
34099+ struct iattr ia;
34100+ struct inode *h_isrc;
34101+
5527c038 34102+ h_isrc = d_inode(h_src);
1facf9fc 34103+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
34104+ ia.ia_mode = h_isrc->i_mode;
34105+ ia.ia_uid = h_isrc->i_uid;
34106+ ia.ia_gid = h_isrc->i_gid;
34107+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
5527c038 34108+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags);
523b37e3
AM
34109+ /* no delegation since it is just created */
34110+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 34111+
34112+ /* is this nfs only? */
34113+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
34114+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
34115+ ia.ia_mode = h_isrc->i_mode;
523b37e3 34116+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 34117+ }
34118+
34119+ return err;
34120+}
34121+
34122+#define AuCpdown_PARENT_OPQ 1
34123+#define AuCpdown_WHED (1 << 1)
34124+#define AuCpdown_MADE_DIR (1 << 2)
34125+#define AuCpdown_DIROPQ (1 << 3)
34126+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
34127+#define au_fset_cpdown(flags, name) \
34128+ do { (flags) |= AuCpdown_##name; } while (0)
34129+#define au_fclr_cpdown(flags, name) \
34130+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 34131+
1facf9fc 34132+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
c2b27bf2 34133+ unsigned int *flags)
1facf9fc 34134+{
34135+ int err;
34136+ struct dentry *opq_dentry;
34137+
34138+ opq_dentry = au_diropq_create(dentry, bdst);
34139+ err = PTR_ERR(opq_dentry);
34140+ if (IS_ERR(opq_dentry))
34141+ goto out;
34142+ dput(opq_dentry);
c2b27bf2 34143+ au_fset_cpdown(*flags, DIROPQ);
1facf9fc 34144+
4f0767ce 34145+out:
1facf9fc 34146+ return err;
34147+}
34148+
34149+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
34150+ struct inode *dir, aufs_bindex_t bdst)
34151+{
34152+ int err;
34153+ struct path h_path;
34154+ struct au_branch *br;
34155+
34156+ br = au_sbr(dentry->d_sb, bdst);
34157+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
34158+ err = PTR_ERR(h_path.dentry);
34159+ if (IS_ERR(h_path.dentry))
34160+ goto out;
34161+
34162+ err = 0;
5527c038 34163+ if (d_is_positive(h_path.dentry)) {
86dc4139 34164+ h_path.mnt = au_br_mnt(br);
1facf9fc 34165+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
34166+ dentry);
34167+ }
34168+ dput(h_path.dentry);
34169+
4f0767ce 34170+out:
1facf9fc 34171+ return err;
34172+}
34173+
34174+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 34175+ struct au_pin *pin,
1facf9fc 34176+ struct dentry *h_parent, void *arg)
34177+{
34178+ int err, rerr;
5afbbe0d 34179+ aufs_bindex_t bopq, btop;
1facf9fc 34180+ struct path h_path;
34181+ struct dentry *parent;
34182+ struct inode *h_dir, *h_inode, *inode, *dir;
c2b27bf2 34183+ unsigned int *flags = arg;
1facf9fc 34184+
5afbbe0d 34185+ btop = au_dbtop(dentry);
1facf9fc 34186+ /* dentry is di-locked */
34187+ parent = dget_parent(dentry);
5527c038
JR
34188+ dir = d_inode(parent);
34189+ h_dir = d_inode(h_parent);
1facf9fc 34190+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
34191+ IMustLock(h_dir);
34192+
86dc4139 34193+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
1facf9fc 34194+ if (unlikely(err < 0))
34195+ goto out;
34196+ h_path.dentry = au_h_dptr(dentry, bdst);
34197+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
cd7a4cd9 34198+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755);
1facf9fc 34199+ if (unlikely(err))
34200+ goto out_put;
c2b27bf2 34201+ au_fset_cpdown(*flags, MADE_DIR);
1facf9fc 34202+
1facf9fc 34203+ bopq = au_dbdiropq(dentry);
c2b27bf2
AM
34204+ au_fclr_cpdown(*flags, WHED);
34205+ au_fclr_cpdown(*flags, DIROPQ);
1facf9fc 34206+ if (au_dbwh(dentry) == bdst)
c2b27bf2
AM
34207+ au_fset_cpdown(*flags, WHED);
34208+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst)
34209+ au_fset_cpdown(*flags, PARENT_OPQ);
5527c038 34210+ h_inode = d_inode(h_path.dentry);
febd17d6 34211+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
c2b27bf2
AM
34212+ if (au_ftest_cpdown(*flags, WHED)) {
34213+ err = au_cpdown_dir_opq(dentry, bdst, flags);
1facf9fc 34214+ if (unlikely(err)) {
febd17d6 34215+ inode_unlock(h_inode);
1facf9fc 34216+ goto out_dir;
34217+ }
34218+ }
34219+
5afbbe0d 34220+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop));
febd17d6 34221+ inode_unlock(h_inode);
1facf9fc 34222+ if (unlikely(err))
34223+ goto out_opq;
34224+
c2b27bf2 34225+ if (au_ftest_cpdown(*flags, WHED)) {
1facf9fc 34226+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
34227+ if (unlikely(err))
34228+ goto out_opq;
34229+ }
34230+
5527c038 34231+ inode = d_inode(dentry);
5afbbe0d
AM
34232+ if (au_ibbot(inode) < bdst)
34233+ au_set_ibbot(inode, bdst);
1facf9fc 34234+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
34235+ au_hi_flags(inode, /*isdir*/1));
076b876e 34236+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0);
1facf9fc 34237+ goto out; /* success */
34238+
34239+ /* revert */
4f0767ce 34240+out_opq:
c2b27bf2 34241+ if (au_ftest_cpdown(*flags, DIROPQ)) {
febd17d6 34242+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 34243+ rerr = au_diropq_remove(dentry, bdst);
febd17d6 34244+ inode_unlock(h_inode);
1facf9fc 34245+ if (unlikely(rerr)) {
523b37e3
AM
34246+ AuIOErr("failed removing diropq for %pd b%d (%d)\n",
34247+ dentry, bdst, rerr);
1facf9fc 34248+ err = -EIO;
34249+ goto out;
34250+ }
34251+ }
4f0767ce 34252+out_dir:
c2b27bf2 34253+ if (au_ftest_cpdown(*flags, MADE_DIR)) {
1facf9fc 34254+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
34255+ if (unlikely(rerr)) {
523b37e3
AM
34256+ AuIOErr("failed removing %pd b%d (%d)\n",
34257+ dentry, bdst, rerr);
1facf9fc 34258+ err = -EIO;
34259+ }
34260+ }
4f0767ce 34261+out_put:
1facf9fc 34262+ au_set_h_dptr(dentry, bdst, NULL);
5afbbe0d
AM
34263+ if (au_dbbot(dentry) == bdst)
34264+ au_update_dbbot(dentry);
4f0767ce 34265+out:
1facf9fc 34266+ dput(parent);
34267+ return err;
34268+}
34269+
34270+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
34271+{
34272+ int err;
c2b27bf2 34273+ unsigned int flags;
1facf9fc 34274+
c2b27bf2
AM
34275+ flags = 0;
34276+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags);
1facf9fc 34277+
34278+ return err;
34279+}
34280+
34281+/* ---------------------------------------------------------------------- */
34282+
34283+/* policies for create */
34284+
c2b27bf2 34285+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
4a4d8108
AM
34286+{
34287+ int err, i, j, ndentry;
34288+ aufs_bindex_t bopq;
34289+ struct au_dcsub_pages dpages;
34290+ struct au_dpage *dpage;
34291+ struct dentry **dentries, *parent, *d;
34292+
34293+ err = au_dpages_init(&dpages, GFP_NOFS);
34294+ if (unlikely(err))
34295+ goto out;
34296+ parent = dget_parent(dentry);
027c5e7a 34297+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
34298+ if (unlikely(err))
34299+ goto out_free;
34300+
34301+ err = bindex;
34302+ for (i = 0; i < dpages.ndpage; i++) {
34303+ dpage = dpages.dpages + i;
34304+ dentries = dpage->dentries;
34305+ ndentry = dpage->ndentry;
34306+ for (j = 0; j < ndentry; j++) {
34307+ d = dentries[j];
34308+ di_read_lock_parent2(d, !AuLock_IR);
34309+ bopq = au_dbdiropq(d);
34310+ di_read_unlock(d, !AuLock_IR);
34311+ if (bopq >= 0 && bopq < err)
34312+ err = bopq;
34313+ }
34314+ }
34315+
34316+out_free:
34317+ dput(parent);
34318+ au_dpages_free(&dpages);
34319+out:
34320+ return err;
34321+}
34322+
1facf9fc 34323+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
34324+{
34325+ for (; bindex >= 0; bindex--)
34326+ if (!au_br_rdonly(au_sbr(sb, bindex)))
34327+ return bindex;
34328+ return -EROFS;
34329+}
34330+
34331+/* top down parent */
392086de
AM
34332+static int au_wbr_create_tdp(struct dentry *dentry,
34333+ unsigned int flags __maybe_unused)
1facf9fc 34334+{
34335+ int err;
5afbbe0d 34336+ aufs_bindex_t btop, bindex;
1facf9fc 34337+ struct super_block *sb;
34338+ struct dentry *parent, *h_parent;
34339+
34340+ sb = dentry->d_sb;
5afbbe0d
AM
34341+ btop = au_dbtop(dentry);
34342+ err = btop;
34343+ if (!au_br_rdonly(au_sbr(sb, btop)))
1facf9fc 34344+ goto out;
34345+
34346+ err = -EROFS;
34347+ parent = dget_parent(dentry);
5afbbe0d 34348+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) {
1facf9fc 34349+ h_parent = au_h_dptr(parent, bindex);
5527c038 34350+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34351+ continue;
34352+
34353+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34354+ err = bindex;
34355+ break;
34356+ }
34357+ }
34358+ dput(parent);
34359+
34360+ /* bottom up here */
4a4d8108 34361+ if (unlikely(err < 0)) {
5afbbe0d 34362+ err = au_wbr_bu(sb, btop - 1);
4a4d8108
AM
34363+ if (err >= 0)
34364+ err = au_wbr_nonopq(dentry, err);
34365+ }
1facf9fc 34366+
4f0767ce 34367+out:
1facf9fc 34368+ AuDbg("b%d\n", err);
34369+ return err;
34370+}
34371+
34372+/* ---------------------------------------------------------------------- */
34373+
34374+/* an exception for the policy other than tdp */
34375+static int au_wbr_create_exp(struct dentry *dentry)
34376+{
34377+ int err;
34378+ aufs_bindex_t bwh, bdiropq;
34379+ struct dentry *parent;
34380+
34381+ err = -1;
34382+ bwh = au_dbwh(dentry);
34383+ parent = dget_parent(dentry);
34384+ bdiropq = au_dbdiropq(parent);
34385+ if (bwh >= 0) {
34386+ if (bdiropq >= 0)
34387+ err = min(bdiropq, bwh);
34388+ else
34389+ err = bwh;
34390+ AuDbg("%d\n", err);
34391+ } else if (bdiropq >= 0) {
34392+ err = bdiropq;
34393+ AuDbg("%d\n", err);
34394+ }
34395+ dput(parent);
34396+
4a4d8108
AM
34397+ if (err >= 0)
34398+ err = au_wbr_nonopq(dentry, err);
34399+
1facf9fc 34400+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
34401+ err = -1;
34402+
34403+ AuDbg("%d\n", err);
34404+ return err;
34405+}
34406+
34407+/* ---------------------------------------------------------------------- */
34408+
34409+/* round robin */
34410+static int au_wbr_create_init_rr(struct super_block *sb)
34411+{
34412+ int err;
34413+
5afbbe0d 34414+ err = au_wbr_bu(sb, au_sbbot(sb));
1facf9fc 34415+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 34416+ /* smp_mb(); */
1facf9fc 34417+
34418+ AuDbg("b%d\n", err);
34419+ return err;
34420+}
34421+
392086de 34422+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags)
1facf9fc 34423+{
34424+ int err, nbr;
34425+ unsigned int u;
5afbbe0d 34426+ aufs_bindex_t bindex, bbot;
1facf9fc 34427+ struct super_block *sb;
34428+ atomic_t *next;
34429+
34430+ err = au_wbr_create_exp(dentry);
34431+ if (err >= 0)
34432+ goto out;
34433+
34434+ sb = dentry->d_sb;
34435+ next = &au_sbi(sb)->si_wbr_rr_next;
5afbbe0d
AM
34436+ bbot = au_sbbot(sb);
34437+ nbr = bbot + 1;
34438+ for (bindex = 0; bindex <= bbot; bindex++) {
392086de 34439+ if (!au_ftest_wbr(flags, DIR)) {
1facf9fc 34440+ err = atomic_dec_return(next) + 1;
34441+ /* modulo for 0 is meaningless */
34442+ if (unlikely(!err))
34443+ err = atomic_dec_return(next) + 1;
34444+ } else
34445+ err = atomic_read(next);
34446+ AuDbg("%d\n", err);
34447+ u = err;
34448+ err = u % nbr;
34449+ AuDbg("%d\n", err);
34450+ if (!au_br_rdonly(au_sbr(sb, err)))
34451+ break;
34452+ err = -EROFS;
34453+ }
34454+
4a4d8108
AM
34455+ if (err >= 0)
34456+ err = au_wbr_nonopq(dentry, err);
34457+
4f0767ce 34458+out:
1facf9fc 34459+ AuDbg("%d\n", err);
34460+ return err;
34461+}
34462+
34463+/* ---------------------------------------------------------------------- */
34464+
34465+/* most free space */
392086de 34466+static void au_mfs(struct dentry *dentry, struct dentry *parent)
1facf9fc 34467+{
34468+ struct super_block *sb;
34469+ struct au_branch *br;
34470+ struct au_wbr_mfs *mfs;
392086de 34471+ struct dentry *h_parent;
5afbbe0d 34472+ aufs_bindex_t bindex, bbot;
1facf9fc 34473+ int err;
34474+ unsigned long long b, bavail;
7f207e10 34475+ struct path h_path;
1facf9fc 34476+ /* reduce the stack usage */
34477+ struct kstatfs *st;
34478+
34479+ st = kmalloc(sizeof(*st), GFP_NOFS);
34480+ if (unlikely(!st)) {
34481+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
34482+ return;
34483+ }
34484+
34485+ bavail = 0;
34486+ sb = dentry->d_sb;
34487+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 34488+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 34489+ mfs->mfs_bindex = -EROFS;
34490+ mfs->mfsrr_bytes = 0;
392086de
AM
34491+ if (!parent) {
34492+ bindex = 0;
5afbbe0d 34493+ bbot = au_sbbot(sb);
392086de 34494+ } else {
5afbbe0d
AM
34495+ bindex = au_dbtop(parent);
34496+ bbot = au_dbtaildir(parent);
392086de
AM
34497+ }
34498+
5afbbe0d 34499+ for (; bindex <= bbot; bindex++) {
392086de
AM
34500+ if (parent) {
34501+ h_parent = au_h_dptr(parent, bindex);
5527c038 34502+ if (!h_parent || d_is_negative(h_parent))
392086de
AM
34503+ continue;
34504+ }
1facf9fc 34505+ br = au_sbr(sb, bindex);
34506+ if (au_br_rdonly(br))
34507+ continue;
34508+
34509+ /* sb->s_root for NFS is unreliable */
86dc4139 34510+ h_path.mnt = au_br_mnt(br);
7f207e10
AM
34511+ h_path.dentry = h_path.mnt->mnt_root;
34512+ err = vfs_statfs(&h_path, st);
1facf9fc 34513+ if (unlikely(err)) {
34514+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
34515+ continue;
34516+ }
34517+
34518+ /* when the available size is equal, select the lower one */
34519+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
34520+ || sizeof(b) < sizeof(st->f_bsize));
34521+ b = st->f_bavail * st->f_bsize;
34522+ br->br_wbr->wbr_bytes = b;
34523+ if (b >= bavail) {
34524+ bavail = b;
34525+ mfs->mfs_bindex = bindex;
34526+ mfs->mfs_jiffy = jiffies;
34527+ }
34528+ }
34529+
34530+ mfs->mfsrr_bytes = bavail;
34531+ AuDbg("b%d\n", mfs->mfs_bindex);
9f237c51 34532+ au_kfree_rcu(st);
1facf9fc 34533+}
34534+
392086de 34535+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34536+{
34537+ int err;
392086de 34538+ struct dentry *parent;
1facf9fc 34539+ struct super_block *sb;
34540+ struct au_wbr_mfs *mfs;
34541+
34542+ err = au_wbr_create_exp(dentry);
34543+ if (err >= 0)
34544+ goto out;
34545+
34546+ sb = dentry->d_sb;
392086de
AM
34547+ parent = NULL;
34548+ if (au_ftest_wbr(flags, PARENT))
34549+ parent = dget_parent(dentry);
1facf9fc 34550+ mfs = &au_sbi(sb)->si_wbr_mfs;
34551+ mutex_lock(&mfs->mfs_lock);
34552+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34553+ || mfs->mfs_bindex < 0
34554+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
392086de 34555+ au_mfs(dentry, parent);
1facf9fc 34556+ mutex_unlock(&mfs->mfs_lock);
34557+ err = mfs->mfs_bindex;
392086de 34558+ dput(parent);
1facf9fc 34559+
4a4d8108
AM
34560+ if (err >= 0)
34561+ err = au_wbr_nonopq(dentry, err);
34562+
4f0767ce 34563+out:
1facf9fc 34564+ AuDbg("b%d\n", err);
34565+ return err;
34566+}
34567+
34568+static int au_wbr_create_init_mfs(struct super_block *sb)
34569+{
34570+ struct au_wbr_mfs *mfs;
34571+
34572+ mfs = &au_sbi(sb)->si_wbr_mfs;
34573+ mutex_init(&mfs->mfs_lock);
34574+ mfs->mfs_jiffy = 0;
34575+ mfs->mfs_bindex = -EROFS;
34576+
34577+ return 0;
34578+}
34579+
34580+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
34581+{
34582+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
34583+ return 0;
34584+}
34585+
34586+/* ---------------------------------------------------------------------- */
34587+
f2c43d5f
AM
34588+/* top down regardless parent, and then mfs */
34589+static int au_wbr_create_tdmfs(struct dentry *dentry,
34590+ unsigned int flags __maybe_unused)
34591+{
34592+ int err;
34593+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs;
34594+ unsigned long long watermark;
34595+ struct super_block *sb;
34596+ struct au_wbr_mfs *mfs;
34597+ struct au_branch *br;
34598+ struct dentry *parent;
34599+
34600+ sb = dentry->d_sb;
34601+ mfs = &au_sbi(sb)->si_wbr_mfs;
34602+ mutex_lock(&mfs->mfs_lock);
34603+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34604+ || mfs->mfs_bindex < 0)
34605+ au_mfs(dentry, /*parent*/NULL);
34606+ watermark = mfs->mfsrr_watermark;
34607+ bmfs = mfs->mfs_bindex;
34608+ mutex_unlock(&mfs->mfs_lock);
34609+
34610+ /* another style of au_wbr_create_exp() */
34611+ bwh = au_dbwh(dentry);
34612+ parent = dget_parent(dentry);
34613+ btail = au_dbtaildir(parent);
34614+ if (bwh >= 0 && bwh < btail)
34615+ btail = bwh;
34616+
34617+ err = au_wbr_nonopq(dentry, btail);
34618+ if (unlikely(err < 0))
34619+ goto out;
34620+ btail = err;
34621+ bfound = -1;
34622+ for (bindex = 0; bindex <= btail; bindex++) {
34623+ br = au_sbr(sb, bindex);
34624+ if (au_br_rdonly(br))
34625+ continue;
34626+ if (br->br_wbr->wbr_bytes > watermark) {
34627+ bfound = bindex;
34628+ break;
34629+ }
34630+ }
34631+ err = bfound;
34632+ if (err < 0)
34633+ err = bmfs;
34634+
34635+out:
34636+ dput(parent);
34637+ AuDbg("b%d\n", err);
34638+ return err;
34639+}
34640+
34641+/* ---------------------------------------------------------------------- */
34642+
1facf9fc 34643+/* most free space and then round robin */
392086de 34644+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags)
1facf9fc 34645+{
34646+ int err;
34647+ struct au_wbr_mfs *mfs;
34648+
392086de 34649+ err = au_wbr_create_mfs(dentry, flags);
1facf9fc 34650+ if (err >= 0) {
34651+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 34652+ mutex_lock(&mfs->mfs_lock);
1facf9fc 34653+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
392086de 34654+ err = au_wbr_create_rr(dentry, flags);
dece6358 34655+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 34656+ }
34657+
34658+ AuDbg("b%d\n", err);
34659+ return err;
34660+}
34661+
34662+static int au_wbr_create_init_mfsrr(struct super_block *sb)
34663+{
34664+ int err;
34665+
34666+ au_wbr_create_init_mfs(sb); /* ignore */
34667+ err = au_wbr_create_init_rr(sb);
34668+
34669+ return err;
34670+}
34671+
34672+/* ---------------------------------------------------------------------- */
34673+
34674+/* top down parent and most free space */
392086de 34675+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34676+{
34677+ int err, e2;
34678+ unsigned long long b;
5afbbe0d 34679+ aufs_bindex_t bindex, btop, bbot;
1facf9fc 34680+ struct super_block *sb;
34681+ struct dentry *parent, *h_parent;
34682+ struct au_branch *br;
34683+
392086de 34684+ err = au_wbr_create_tdp(dentry, flags);
1facf9fc 34685+ if (unlikely(err < 0))
34686+ goto out;
34687+ parent = dget_parent(dentry);
5afbbe0d
AM
34688+ btop = au_dbtop(parent);
34689+ bbot = au_dbtaildir(parent);
34690+ if (btop == bbot)
1facf9fc 34691+ goto out_parent; /* success */
34692+
392086de 34693+ e2 = au_wbr_create_mfs(dentry, flags);
1facf9fc 34694+ if (e2 < 0)
34695+ goto out_parent; /* success */
34696+
34697+ /* when the available size is equal, select upper one */
34698+ sb = dentry->d_sb;
34699+ br = au_sbr(sb, err);
34700+ b = br->br_wbr->wbr_bytes;
34701+ AuDbg("b%d, %llu\n", err, b);
34702+
5afbbe0d 34703+ for (bindex = btop; bindex <= bbot; bindex++) {
1facf9fc 34704+ h_parent = au_h_dptr(parent, bindex);
5527c038 34705+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34706+ continue;
34707+
34708+ br = au_sbr(sb, bindex);
34709+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
34710+ b = br->br_wbr->wbr_bytes;
34711+ err = bindex;
34712+ AuDbg("b%d, %llu\n", err, b);
34713+ }
34714+ }
34715+
4a4d8108
AM
34716+ if (err >= 0)
34717+ err = au_wbr_nonopq(dentry, err);
34718+
4f0767ce 34719+out_parent:
1facf9fc 34720+ dput(parent);
4f0767ce 34721+out:
1facf9fc 34722+ AuDbg("b%d\n", err);
34723+ return err;
34724+}
34725+
34726+/* ---------------------------------------------------------------------- */
34727+
392086de
AM
34728+/*
34729+ * - top down parent
34730+ * - most free space with parent
34731+ * - most free space round-robin regardless parent
34732+ */
34733+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags)
34734+{
34735+ int err;
34736+ unsigned long long watermark;
34737+ struct super_block *sb;
34738+ struct au_branch *br;
34739+ struct au_wbr_mfs *mfs;
34740+
34741+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT);
34742+ if (unlikely(err < 0))
34743+ goto out;
34744+
34745+ sb = dentry->d_sb;
34746+ br = au_sbr(sb, err);
34747+ mfs = &au_sbi(sb)->si_wbr_mfs;
34748+ mutex_lock(&mfs->mfs_lock);
34749+ watermark = mfs->mfsrr_watermark;
34750+ mutex_unlock(&mfs->mfs_lock);
34751+ if (br->br_wbr->wbr_bytes < watermark)
34752+ /* regardless the parent dir */
34753+ err = au_wbr_create_mfsrr(dentry, flags);
34754+
34755+out:
34756+ AuDbg("b%d\n", err);
34757+ return err;
34758+}
34759+
34760+/* ---------------------------------------------------------------------- */
34761+
1facf9fc 34762+/* policies for copyup */
34763+
34764+/* top down parent */
34765+static int au_wbr_copyup_tdp(struct dentry *dentry)
34766+{
392086de 34767+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0);
1facf9fc 34768+}
34769+
34770+/* bottom up parent */
34771+static int au_wbr_copyup_bup(struct dentry *dentry)
34772+{
34773+ int err;
5afbbe0d 34774+ aufs_bindex_t bindex, btop;
1facf9fc 34775+ struct dentry *parent, *h_parent;
34776+ struct super_block *sb;
34777+
34778+ err = -EROFS;
34779+ sb = dentry->d_sb;
34780+ parent = dget_parent(dentry);
5afbbe0d
AM
34781+ btop = au_dbtop(parent);
34782+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) {
1facf9fc 34783+ h_parent = au_h_dptr(parent, bindex);
5527c038 34784+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34785+ continue;
34786+
34787+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34788+ err = bindex;
34789+ break;
34790+ }
34791+ }
34792+ dput(parent);
34793+
34794+ /* bottom up here */
34795+ if (unlikely(err < 0))
5afbbe0d 34796+ err = au_wbr_bu(sb, btop - 1);
1facf9fc 34797+
34798+ AuDbg("b%d\n", err);
34799+ return err;
34800+}
34801+
34802+/* bottom up */
5afbbe0d 34803+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop)
1facf9fc 34804+{
34805+ int err;
34806+
5afbbe0d 34807+ err = au_wbr_bu(dentry->d_sb, btop);
4a4d8108 34808+ AuDbg("b%d\n", err);
5afbbe0d 34809+ if (err > btop)
4a4d8108 34810+ err = au_wbr_nonopq(dentry, err);
1facf9fc 34811+
34812+ AuDbg("b%d\n", err);
34813+ return err;
34814+}
34815+
076b876e
AM
34816+static int au_wbr_copyup_bu(struct dentry *dentry)
34817+{
34818+ int err;
5afbbe0d 34819+ aufs_bindex_t btop;
076b876e 34820+
5afbbe0d
AM
34821+ btop = au_dbtop(dentry);
34822+ err = au_wbr_do_copyup_bu(dentry, btop);
076b876e
AM
34823+ return err;
34824+}
34825+
1facf9fc 34826+/* ---------------------------------------------------------------------- */
34827+
34828+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
34829+ [AuWbrCopyup_TDP] = {
34830+ .copyup = au_wbr_copyup_tdp
34831+ },
34832+ [AuWbrCopyup_BUP] = {
34833+ .copyup = au_wbr_copyup_bup
34834+ },
34835+ [AuWbrCopyup_BU] = {
34836+ .copyup = au_wbr_copyup_bu
34837+ }
34838+};
34839+
34840+struct au_wbr_create_operations au_wbr_create_ops[] = {
34841+ [AuWbrCreate_TDP] = {
34842+ .create = au_wbr_create_tdp
34843+ },
34844+ [AuWbrCreate_RR] = {
34845+ .create = au_wbr_create_rr,
34846+ .init = au_wbr_create_init_rr
34847+ },
34848+ [AuWbrCreate_MFS] = {
34849+ .create = au_wbr_create_mfs,
34850+ .init = au_wbr_create_init_mfs,
34851+ .fin = au_wbr_create_fin_mfs
34852+ },
34853+ [AuWbrCreate_MFSV] = {
34854+ .create = au_wbr_create_mfs,
34855+ .init = au_wbr_create_init_mfs,
34856+ .fin = au_wbr_create_fin_mfs
34857+ },
34858+ [AuWbrCreate_MFSRR] = {
34859+ .create = au_wbr_create_mfsrr,
34860+ .init = au_wbr_create_init_mfsrr,
34861+ .fin = au_wbr_create_fin_mfs
34862+ },
34863+ [AuWbrCreate_MFSRRV] = {
34864+ .create = au_wbr_create_mfsrr,
34865+ .init = au_wbr_create_init_mfsrr,
34866+ .fin = au_wbr_create_fin_mfs
34867+ },
f2c43d5f
AM
34868+ [AuWbrCreate_TDMFS] = {
34869+ .create = au_wbr_create_tdmfs,
34870+ .init = au_wbr_create_init_mfs,
34871+ .fin = au_wbr_create_fin_mfs
34872+ },
34873+ [AuWbrCreate_TDMFSV] = {
34874+ .create = au_wbr_create_tdmfs,
34875+ .init = au_wbr_create_init_mfs,
34876+ .fin = au_wbr_create_fin_mfs
34877+ },
1facf9fc 34878+ [AuWbrCreate_PMFS] = {
34879+ .create = au_wbr_create_pmfs,
34880+ .init = au_wbr_create_init_mfs,
34881+ .fin = au_wbr_create_fin_mfs
34882+ },
34883+ [AuWbrCreate_PMFSV] = {
34884+ .create = au_wbr_create_pmfs,
34885+ .init = au_wbr_create_init_mfs,
34886+ .fin = au_wbr_create_fin_mfs
392086de
AM
34887+ },
34888+ [AuWbrCreate_PMFSRR] = {
34889+ .create = au_wbr_create_pmfsrr,
34890+ .init = au_wbr_create_init_mfsrr,
34891+ .fin = au_wbr_create_fin_mfs
34892+ },
34893+ [AuWbrCreate_PMFSRRV] = {
34894+ .create = au_wbr_create_pmfsrr,
34895+ .init = au_wbr_create_init_mfsrr,
34896+ .fin = au_wbr_create_fin_mfs
1facf9fc 34897+ }
34898+};
7f207e10 34899diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
eca34b5c
AM
34900--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
34901+++ linux/fs/aufs/whout.c 2019-07-11 15:42:14.475571481 +0200
062440b3 34902@@ -0,0 +1,1062 @@
cd7a4cd9 34903+// SPDX-License-Identifier: GPL-2.0
1facf9fc 34904+/*
ba1aed25 34905+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 34906+ *
34907+ * This program, aufs is free software; you can redistribute it and/or modify
34908+ * it under the terms of the GNU General Public License as published by
34909+ * the Free Software Foundation; either version 2 of the License, or
34910+ * (at your option) any later version.
dece6358
AM
34911+ *
34912+ * This program is distributed in the hope that it will be useful,
34913+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34914+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34915+ * GNU General Public License for more details.
34916+ *
34917+ * You should have received a copy of the GNU General Public License
523b37e3 34918+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34919+ */
34920+
34921+/*
34922+ * whiteout for logical deletion and opaque directory
34923+ */
34924+
1facf9fc 34925+#include "aufs.h"
34926+
cd7a4cd9 34927+#define WH_MASK 0444
1facf9fc 34928+
34929+/*
34930+ * If a directory contains this file, then it is opaque. We start with the
34931+ * .wh. flag so that it is blocked by lookup.
34932+ */
0c3ec466
AM
34933+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
34934+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 34935+
34936+/*
34937+ * generate whiteout name, which is NOT terminated by NULL.
34938+ * @name: original d_name.name
34939+ * @len: original d_name.len
34940+ * @wh: whiteout qstr
34941+ * returns zero when succeeds, otherwise error.
34942+ * succeeded value as wh->name should be freed by kfree().
34943+ */
34944+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
34945+{
34946+ char *p;
34947+
34948+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
34949+ return -ENAMETOOLONG;
34950+
34951+ wh->len = name->len + AUFS_WH_PFX_LEN;
34952+ p = kmalloc(wh->len, GFP_NOFS);
34953+ wh->name = p;
34954+ if (p) {
34955+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
34956+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
34957+ /* smp_mb(); */
34958+ return 0;
34959+ }
34960+ return -ENOMEM;
34961+}
34962+
34963+/* ---------------------------------------------------------------------- */
34964+
34965+/*
34966+ * test if the @wh_name exists under @h_parent.
34967+ * @try_sio specifies the necessary of super-io.
34968+ */
076b876e 34969+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio)
1facf9fc 34970+{
34971+ int err;
34972+ struct dentry *wh_dentry;
1facf9fc 34973+
1facf9fc 34974+ if (!try_sio)
b4510431 34975+ wh_dentry = vfsub_lkup_one(wh_name, h_parent);
1facf9fc 34976+ else
076b876e 34977+ wh_dentry = au_sio_lkup_one(wh_name, h_parent);
1facf9fc 34978+ err = PTR_ERR(wh_dentry);
2000de60
JR
34979+ if (IS_ERR(wh_dentry)) {
34980+ if (err == -ENAMETOOLONG)
34981+ err = 0;
1facf9fc 34982+ goto out;
2000de60 34983+ }
1facf9fc 34984+
34985+ err = 0;
5527c038 34986+ if (d_is_negative(wh_dentry))
1facf9fc 34987+ goto out_wh; /* success */
34988+
34989+ err = 1;
7e9cd9fe 34990+ if (d_is_reg(wh_dentry))
1facf9fc 34991+ goto out_wh; /* success */
34992+
34993+ err = -EIO;
523b37e3 34994+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n",
5527c038 34995+ wh_dentry, d_inode(wh_dentry)->i_mode);
1facf9fc 34996+
4f0767ce 34997+out_wh:
1facf9fc 34998+ dput(wh_dentry);
4f0767ce 34999+out:
1facf9fc 35000+ return err;
35001+}
35002+
35003+/*
35004+ * test if the @h_dentry sets opaque or not.
35005+ */
076b876e 35006+int au_diropq_test(struct dentry *h_dentry)
1facf9fc 35007+{
35008+ int err;
35009+ struct inode *h_dir;
35010+
5527c038 35011+ h_dir = d_inode(h_dentry);
076b876e 35012+ err = au_wh_test(h_dentry, &diropq_name,
1facf9fc 35013+ au_test_h_perm_sio(h_dir, MAY_EXEC));
35014+ return err;
35015+}
35016+
35017+/*
35018+ * returns a negative dentry whose name is unique and temporary.
35019+ */
35020+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
35021+ struct qstr *prefix)
35022+{
1facf9fc 35023+ struct dentry *dentry;
35024+ int i;
027c5e7a 35025+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 35026+ *name, *p;
027c5e7a 35027+ /* strict atomic_t is unnecessary here */
1facf9fc 35028+ static unsigned short cnt;
35029+ struct qstr qs;
35030+
4a4d8108
AM
35031+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
35032+
1facf9fc 35033+ name = defname;
027c5e7a
AM
35034+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
35035+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 35036+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 35037+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 35038+ goto out;
35039+ dentry = ERR_PTR(-ENOMEM);
35040+ name = kmalloc(qs.len + 1, GFP_NOFS);
35041+ if (unlikely(!name))
35042+ goto out;
35043+ }
35044+
35045+ /* doubly whiteout-ed */
35046+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
35047+ p = name + AUFS_WH_PFX_LEN * 2;
35048+ memcpy(p, prefix->name, prefix->len);
35049+ p += prefix->len;
35050+ *p++ = '.';
4a4d8108 35051+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 35052+
35053+ qs.name = name;
35054+ for (i = 0; i < 3; i++) {
b752ccd1 35055+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
076b876e 35056+ dentry = au_sio_lkup_one(&qs, h_parent);
5527c038 35057+ if (IS_ERR(dentry) || d_is_negative(dentry))
1facf9fc 35058+ goto out_name;
35059+ dput(dentry);
35060+ }
0c3ec466 35061+ /* pr_warn("could not get random name\n"); */
1facf9fc 35062+ dentry = ERR_PTR(-EEXIST);
35063+ AuDbg("%.*s\n", AuLNPair(&qs));
35064+ BUG();
35065+
4f0767ce 35066+out_name:
1facf9fc 35067+ if (name != defname)
9f237c51 35068+ au_kfree_try_rcu(name);
4f0767ce 35069+out:
4a4d8108 35070+ AuTraceErrPtr(dentry);
1facf9fc 35071+ return dentry;
1facf9fc 35072+}
35073+
35074+/*
35075+ * rename the @h_dentry on @br to the whiteouted temporary name.
35076+ */
35077+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
35078+{
35079+ int err;
35080+ struct path h_path = {
86dc4139 35081+ .mnt = au_br_mnt(br)
1facf9fc 35082+ };
523b37e3 35083+ struct inode *h_dir, *delegated;
1facf9fc 35084+ struct dentry *h_parent;
35085+
35086+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 35087+ h_dir = d_inode(h_parent);
1facf9fc 35088+ IMustLock(h_dir);
35089+
35090+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
35091+ err = PTR_ERR(h_path.dentry);
35092+ if (IS_ERR(h_path.dentry))
35093+ goto out;
35094+
35095+ /* under the same dir, no need to lock_rename() */
523b37e3 35096+ delegated = NULL;
f2c43d5f
AM
35097+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated,
35098+ /*flags*/0);
1facf9fc 35099+ AuTraceErr(err);
523b37e3
AM
35100+ if (unlikely(err == -EWOULDBLOCK)) {
35101+ pr_warn("cannot retry for NFSv4 delegation"
35102+ " for an internal rename\n");
35103+ iput(delegated);
35104+ }
1facf9fc 35105+ dput(h_path.dentry);
35106+
4f0767ce 35107+out:
4a4d8108 35108+ AuTraceErr(err);
1facf9fc 35109+ return err;
35110+}
35111+
35112+/* ---------------------------------------------------------------------- */
35113+/*
35114+ * functions for removing a whiteout
35115+ */
35116+
35117+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
35118+{
523b37e3
AM
35119+ int err, force;
35120+ struct inode *delegated;
1facf9fc 35121+
35122+ /*
35123+ * forces superio when the dir has a sticky bit.
35124+ * this may be a violation of unix fs semantics.
35125+ */
35126+ force = (h_dir->i_mode & S_ISVTX)
5527c038 35127+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid);
523b37e3
AM
35128+ delegated = NULL;
35129+ err = vfsub_unlink(h_dir, h_path, &delegated, force);
35130+ if (unlikely(err == -EWOULDBLOCK)) {
35131+ pr_warn("cannot retry for NFSv4 delegation"
35132+ " for an internal unlink\n");
35133+ iput(delegated);
35134+ }
35135+ return err;
1facf9fc 35136+}
35137+
35138+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
35139+ struct dentry *dentry)
35140+{
35141+ int err;
35142+
35143+ err = do_unlink_wh(h_dir, h_path);
35144+ if (!err && dentry)
35145+ au_set_dbwh(dentry, -1);
35146+
35147+ return err;
35148+}
35149+
35150+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
35151+ struct au_branch *br)
35152+{
35153+ int err;
35154+ struct path h_path = {
86dc4139 35155+ .mnt = au_br_mnt(br)
1facf9fc 35156+ };
35157+
35158+ err = 0;
b4510431 35159+ h_path.dentry = vfsub_lkup_one(wh, h_parent);
1facf9fc 35160+ if (IS_ERR(h_path.dentry))
35161+ err = PTR_ERR(h_path.dentry);
35162+ else {
5527c038
JR
35163+ if (d_is_reg(h_path.dentry))
35164+ err = do_unlink_wh(d_inode(h_parent), &h_path);
1facf9fc 35165+ dput(h_path.dentry);
35166+ }
35167+
35168+ return err;
35169+}
35170+
35171+/* ---------------------------------------------------------------------- */
35172+/*
35173+ * initialize/clean whiteout for a branch
35174+ */
35175+
35176+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
35177+ const int isdir)
35178+{
35179+ int err;
523b37e3 35180+ struct inode *delegated;
1facf9fc 35181+
5527c038 35182+ if (d_is_negative(whpath->dentry))
1facf9fc 35183+ return;
35184+
86dc4139
AM
35185+ if (isdir)
35186+ err = vfsub_rmdir(h_dir, whpath);
523b37e3
AM
35187+ else {
35188+ delegated = NULL;
35189+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0);
35190+ if (unlikely(err == -EWOULDBLOCK)) {
35191+ pr_warn("cannot retry for NFSv4 delegation"
35192+ " for an internal unlink\n");
35193+ iput(delegated);
35194+ }
35195+ }
1facf9fc 35196+ if (unlikely(err))
523b37e3
AM
35197+ pr_warn("failed removing %pd (%d), ignored.\n",
35198+ whpath->dentry, err);
1facf9fc 35199+}
35200+
35201+static int test_linkable(struct dentry *h_root)
35202+{
5527c038 35203+ struct inode *h_dir = d_inode(h_root);
1facf9fc 35204+
35205+ if (h_dir->i_op->link)
35206+ return 0;
35207+
523b37e3
AM
35208+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n",
35209+ h_root, au_sbtype(h_root->d_sb));
1facf9fc 35210+ return -ENOSYS;
35211+}
35212+
35213+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
35214+static int au_whdir(struct inode *h_dir, struct path *path)
35215+{
35216+ int err;
35217+
35218+ err = -EEXIST;
5527c038 35219+ if (d_is_negative(path->dentry)) {
cd7a4cd9 35220+ int mode = 0700;
1facf9fc 35221+
35222+ if (au_test_nfs(path->dentry->d_sb))
cd7a4cd9 35223+ mode |= 0111;
86dc4139 35224+ err = vfsub_mkdir(h_dir, path, mode);
2000de60 35225+ } else if (d_is_dir(path->dentry))
1facf9fc 35226+ err = 0;
35227+ else
523b37e3 35228+ pr_err("unknown %pd exists\n", path->dentry);
1facf9fc 35229+
35230+ return err;
35231+}
35232+
35233+struct au_wh_base {
35234+ const struct qstr *name;
35235+ struct dentry *dentry;
35236+};
35237+
35238+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
35239+ struct path *h_path)
35240+{
35241+ h_path->dentry = base[AuBrWh_BASE].dentry;
35242+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35243+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35244+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35245+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35246+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35247+}
35248+
35249+/*
35250+ * returns tri-state,
c1595e42 35251+ * minus: error, caller should print the message
acd2b654 35252+ * zero: success
c1595e42 35253+ * plus: error, caller should NOT print the message
1facf9fc 35254+ */
35255+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
35256+ int do_plink, struct au_wh_base base[],
35257+ struct path *h_path)
35258+{
35259+ int err;
35260+ struct inode *h_dir;
35261+
5527c038 35262+ h_dir = d_inode(h_root);
1facf9fc 35263+ h_path->dentry = base[AuBrWh_BASE].dentry;
35264+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35265+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35266+ if (do_plink) {
35267+ err = test_linkable(h_root);
35268+ if (unlikely(err)) {
35269+ err = 1;
35270+ goto out;
35271+ }
35272+
35273+ err = au_whdir(h_dir, h_path);
35274+ if (unlikely(err))
35275+ goto out;
35276+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35277+ } else
35278+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35279+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35280+ err = au_whdir(h_dir, h_path);
35281+ if (unlikely(err))
35282+ goto out;
35283+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35284+
4f0767ce 35285+out:
1facf9fc 35286+ return err;
35287+}
35288+
35289+/*
35290+ * for the moment, aufs supports the branch filesystem which does not support
35291+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
35292+ * copyup failed. finally, such filesystem will not be used as the writable
35293+ * branch.
35294+ *
35295+ * returns tri-state, see above.
35296+ */
35297+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
35298+ int do_plink, struct au_wh_base base[],
35299+ struct path *h_path)
35300+{
35301+ int err;
35302+ struct inode *h_dir;
35303+
1308ab2a 35304+ WbrWhMustWriteLock(wbr);
35305+
1facf9fc 35306+ err = test_linkable(h_root);
35307+ if (unlikely(err)) {
35308+ err = 1;
35309+ goto out;
35310+ }
35311+
35312+ /*
35313+ * todo: should this create be done in /sbin/mount.aufs helper?
35314+ */
35315+ err = -EEXIST;
5527c038
JR
35316+ h_dir = d_inode(h_root);
35317+ if (d_is_negative(base[AuBrWh_BASE].dentry)) {
86dc4139
AM
35318+ h_path->dentry = base[AuBrWh_BASE].dentry;
35319+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true);
7e9cd9fe 35320+ } else if (d_is_reg(base[AuBrWh_BASE].dentry))
1facf9fc 35321+ err = 0;
35322+ else
523b37e3 35323+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry);
1facf9fc 35324+ if (unlikely(err))
35325+ goto out;
35326+
35327+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35328+ if (do_plink) {
35329+ err = au_whdir(h_dir, h_path);
35330+ if (unlikely(err))
35331+ goto out;
35332+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35333+ } else
35334+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35335+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
35336+
35337+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35338+ err = au_whdir(h_dir, h_path);
35339+ if (unlikely(err))
35340+ goto out;
35341+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35342+
4f0767ce 35343+out:
1facf9fc 35344+ return err;
35345+}
35346+
35347+/*
35348+ * initialize the whiteout base file/dir for @br.
35349+ */
86dc4139 35350+int au_wh_init(struct au_branch *br, struct super_block *sb)
1facf9fc 35351+{
35352+ int err, i;
35353+ const unsigned char do_plink
35354+ = !!au_opt_test(au_mntflags(sb), PLINK);
1facf9fc 35355+ struct inode *h_dir;
86dc4139
AM
35356+ struct path path = br->br_path;
35357+ struct dentry *h_root = path.dentry;
1facf9fc 35358+ struct au_wbr *wbr = br->br_wbr;
35359+ static const struct qstr base_name[] = {
0c3ec466
AM
35360+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
35361+ sizeof(AUFS_BASE_NAME) - 1),
35362+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
35363+ sizeof(AUFS_PLINKDIR_NAME) - 1),
35364+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
35365+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 35366+ };
35367+ struct au_wh_base base[] = {
35368+ [AuBrWh_BASE] = {
35369+ .name = base_name + AuBrWh_BASE,
35370+ .dentry = NULL
35371+ },
35372+ [AuBrWh_PLINK] = {
35373+ .name = base_name + AuBrWh_PLINK,
35374+ .dentry = NULL
35375+ },
35376+ [AuBrWh_ORPH] = {
35377+ .name = base_name + AuBrWh_ORPH,
35378+ .dentry = NULL
35379+ }
35380+ };
35381+
1308ab2a 35382+ if (wbr)
35383+ WbrWhMustWriteLock(wbr);
1facf9fc 35384+
1facf9fc 35385+ for (i = 0; i < AuBrWh_Last; i++) {
35386+ /* doubly whiteouted */
35387+ struct dentry *d;
35388+
35389+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
35390+ err = PTR_ERR(d);
35391+ if (IS_ERR(d))
35392+ goto out;
35393+
35394+ base[i].dentry = d;
35395+ AuDebugOn(wbr
35396+ && wbr->wbr_wh[i]
35397+ && wbr->wbr_wh[i] != base[i].dentry);
35398+ }
35399+
35400+ if (wbr)
35401+ for (i = 0; i < AuBrWh_Last; i++) {
35402+ dput(wbr->wbr_wh[i]);
35403+ wbr->wbr_wh[i] = NULL;
35404+ }
35405+
35406+ err = 0;
1e00d052 35407+ if (!au_br_writable(br->br_perm)) {
5527c038 35408+ h_dir = d_inode(h_root);
1facf9fc 35409+ au_wh_init_ro(h_dir, base, &path);
1e00d052 35410+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 35411+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
35412+ if (err > 0)
35413+ goto out;
35414+ else if (err)
35415+ goto out_err;
1e00d052 35416+ } else {
1facf9fc 35417+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
35418+ if (err > 0)
35419+ goto out;
35420+ else if (err)
35421+ goto out_err;
1facf9fc 35422+ }
35423+ goto out; /* success */
35424+
4f0767ce 35425+out_err:
523b37e3
AM
35426+ pr_err("an error(%d) on the writable branch %pd(%s)\n",
35427+ err, h_root, au_sbtype(h_root->d_sb));
4f0767ce 35428+out:
1facf9fc 35429+ for (i = 0; i < AuBrWh_Last; i++)
35430+ dput(base[i].dentry);
35431+ return err;
35432+}
35433+
35434+/* ---------------------------------------------------------------------- */
35435+/*
35436+ * whiteouts are all hard-linked usually.
35437+ * when its link count reaches a ceiling, we create a new whiteout base
35438+ * asynchronously.
35439+ */
35440+
35441+struct reinit_br_wh {
35442+ struct super_block *sb;
35443+ struct au_branch *br;
35444+};
35445+
35446+static void reinit_br_wh(void *arg)
35447+{
35448+ int err;
35449+ aufs_bindex_t bindex;
35450+ struct path h_path;
35451+ struct reinit_br_wh *a = arg;
35452+ struct au_wbr *wbr;
523b37e3 35453+ struct inode *dir, *delegated;
1facf9fc 35454+ struct dentry *h_root;
35455+ struct au_hinode *hdir;
35456+
35457+ err = 0;
35458+ wbr = a->br->br_wbr;
35459+ /* big aufs lock */
35460+ si_noflush_write_lock(a->sb);
35461+ if (!au_br_writable(a->br->br_perm))
35462+ goto out;
35463+ bindex = au_br_index(a->sb, a->br->br_id);
35464+ if (unlikely(bindex < 0))
35465+ goto out;
35466+
1308ab2a 35467+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
5527c038 35468+ dir = d_inode(a->sb->s_root);
1facf9fc 35469+ hdir = au_hi(dir, bindex);
35470+ h_root = au_h_dptr(a->sb->s_root, bindex);
86dc4139 35471+ AuDebugOn(h_root != au_br_dentry(a->br));
1facf9fc 35472+
5afbbe0d 35473+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 35474+ wbr_wh_write_lock(wbr);
35475+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
35476+ h_root, a->br);
35477+ if (!err) {
86dc4139
AM
35478+ h_path.dentry = wbr->wbr_whbase;
35479+ h_path.mnt = au_br_mnt(a->br);
523b37e3
AM
35480+ delegated = NULL;
35481+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated,
35482+ /*force*/0);
35483+ if (unlikely(err == -EWOULDBLOCK)) {
35484+ pr_warn("cannot retry for NFSv4 delegation"
35485+ " for an internal unlink\n");
35486+ iput(delegated);
35487+ }
1facf9fc 35488+ } else {
523b37e3 35489+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase);
1facf9fc 35490+ err = 0;
35491+ }
35492+ dput(wbr->wbr_whbase);
35493+ wbr->wbr_whbase = NULL;
35494+ if (!err)
86dc4139 35495+ err = au_wh_init(a->br, a->sb);
1facf9fc 35496+ wbr_wh_write_unlock(wbr);
5afbbe0d 35497+ au_hn_inode_unlock(hdir);
1308ab2a 35498+ di_read_unlock(a->sb->s_root, AuLock_IR);
076b876e
AM
35499+ if (!err)
35500+ au_fhsm_wrote(a->sb, bindex, /*force*/0);
1facf9fc 35501+
4f0767ce 35502+out:
1facf9fc 35503+ if (wbr)
35504+ atomic_dec(&wbr->wbr_wh_running);
acd2b654 35505+ au_lcnt_dec(&a->br->br_count);
1facf9fc 35506+ si_write_unlock(a->sb);
027c5e7a 35507+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
9f237c51 35508+ au_kfree_rcu(a);
1facf9fc 35509+ if (unlikely(err))
35510+ AuIOErr("err %d\n", err);
35511+}
35512+
35513+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
35514+{
35515+ int do_dec, wkq_err;
35516+ struct reinit_br_wh *arg;
35517+
35518+ do_dec = 1;
35519+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
35520+ goto out;
35521+
35522+ /* ignore ENOMEM */
35523+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
35524+ if (arg) {
35525+ /*
35526+ * dec(wh_running), kfree(arg) and dec(br_count)
35527+ * in reinit function
35528+ */
35529+ arg->sb = sb;
35530+ arg->br = br;
acd2b654 35531+ au_lcnt_inc(&br->br_count);
53392da6 35532+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 35533+ if (unlikely(wkq_err)) {
35534+ atomic_dec(&br->br_wbr->wbr_wh_running);
acd2b654 35535+ au_lcnt_dec(&br->br_count);
9f237c51 35536+ au_kfree_rcu(arg);
1facf9fc 35537+ }
35538+ do_dec = 0;
35539+ }
35540+
4f0767ce 35541+out:
1facf9fc 35542+ if (do_dec)
35543+ atomic_dec(&br->br_wbr->wbr_wh_running);
35544+}
35545+
35546+/* ---------------------------------------------------------------------- */
35547+
35548+/*
35549+ * create the whiteout @wh.
35550+ */
35551+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
35552+ struct dentry *wh)
35553+{
35554+ int err;
35555+ struct path h_path = {
35556+ .dentry = wh
35557+ };
35558+ struct au_branch *br;
35559+ struct au_wbr *wbr;
35560+ struct dentry *h_parent;
523b37e3 35561+ struct inode *h_dir, *delegated;
1facf9fc 35562+
35563+ h_parent = wh->d_parent; /* dir inode is locked */
5527c038 35564+ h_dir = d_inode(h_parent);
1facf9fc 35565+ IMustLock(h_dir);
35566+
35567+ br = au_sbr(sb, bindex);
86dc4139 35568+ h_path.mnt = au_br_mnt(br);
1facf9fc 35569+ wbr = br->br_wbr;
35570+ wbr_wh_read_lock(wbr);
35571+ if (wbr->wbr_whbase) {
523b37e3
AM
35572+ delegated = NULL;
35573+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated);
35574+ if (unlikely(err == -EWOULDBLOCK)) {
35575+ pr_warn("cannot retry for NFSv4 delegation"
35576+ " for an internal link\n");
35577+ iput(delegated);
35578+ }
1facf9fc 35579+ if (!err || err != -EMLINK)
35580+ goto out;
35581+
35582+ /* link count full. re-initialize br_whbase. */
35583+ kick_reinit_br_wh(sb, br);
35584+ }
35585+
35586+ /* return this error in this context */
b4510431 35587+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true);
076b876e
AM
35588+ if (!err)
35589+ au_fhsm_wrote(sb, bindex, /*force*/0);
1facf9fc 35590+
4f0767ce 35591+out:
1facf9fc 35592+ wbr_wh_read_unlock(wbr);
35593+ return err;
35594+}
35595+
35596+/* ---------------------------------------------------------------------- */
35597+
35598+/*
35599+ * create or remove the diropq.
35600+ */
35601+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
35602+ unsigned int flags)
35603+{
35604+ struct dentry *opq_dentry, *h_dentry;
35605+ struct super_block *sb;
35606+ struct au_branch *br;
35607+ int err;
35608+
35609+ sb = dentry->d_sb;
35610+ br = au_sbr(sb, bindex);
35611+ h_dentry = au_h_dptr(dentry, bindex);
b4510431 35612+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
1facf9fc 35613+ if (IS_ERR(opq_dentry))
35614+ goto out;
35615+
35616+ if (au_ftest_diropq(flags, CREATE)) {
35617+ err = link_or_create_wh(sb, bindex, opq_dentry);
35618+ if (!err) {
35619+ au_set_dbdiropq(dentry, bindex);
35620+ goto out; /* success */
35621+ }
35622+ } else {
35623+ struct path tmp = {
35624+ .dentry = opq_dentry,
86dc4139 35625+ .mnt = au_br_mnt(br)
1facf9fc 35626+ };
5527c038 35627+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp);
1facf9fc 35628+ if (!err)
35629+ au_set_dbdiropq(dentry, -1);
35630+ }
35631+ dput(opq_dentry);
35632+ opq_dentry = ERR_PTR(err);
35633+
4f0767ce 35634+out:
1facf9fc 35635+ return opq_dentry;
35636+}
35637+
35638+struct do_diropq_args {
35639+ struct dentry **errp;
35640+ struct dentry *dentry;
35641+ aufs_bindex_t bindex;
35642+ unsigned int flags;
35643+};
35644+
35645+static void call_do_diropq(void *args)
35646+{
35647+ struct do_diropq_args *a = args;
35648+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
35649+}
35650+
35651+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
35652+ unsigned int flags)
35653+{
35654+ struct dentry *diropq, *h_dentry;
35655+
35656+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 35657+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE))
1facf9fc 35658+ diropq = do_diropq(dentry, bindex, flags);
35659+ else {
35660+ int wkq_err;
35661+ struct do_diropq_args args = {
35662+ .errp = &diropq,
35663+ .dentry = dentry,
35664+ .bindex = bindex,
35665+ .flags = flags
35666+ };
35667+
35668+ wkq_err = au_wkq_wait(call_do_diropq, &args);
35669+ if (unlikely(wkq_err))
35670+ diropq = ERR_PTR(wkq_err);
35671+ }
35672+
35673+ return diropq;
35674+}
35675+
35676+/* ---------------------------------------------------------------------- */
35677+
35678+/*
35679+ * lookup whiteout dentry.
35680+ * @h_parent: lower parent dentry which must exist and be locked
35681+ * @base_name: name of dentry which will be whiteouted
35682+ * returns dentry for whiteout.
35683+ */
35684+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
35685+ struct au_branch *br)
35686+{
35687+ int err;
35688+ struct qstr wh_name;
35689+ struct dentry *wh_dentry;
35690+
35691+ err = au_wh_name_alloc(&wh_name, base_name);
35692+ wh_dentry = ERR_PTR(err);
35693+ if (!err) {
b4510431 35694+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
9f237c51 35695+ au_kfree_try_rcu(wh_name.name);
1facf9fc 35696+ }
35697+ return wh_dentry;
35698+}
35699+
35700+/*
35701+ * link/create a whiteout for @dentry on @bindex.
35702+ */
35703+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
35704+ struct dentry *h_parent)
35705+{
35706+ struct dentry *wh_dentry;
35707+ struct super_block *sb;
35708+ int err;
35709+
35710+ sb = dentry->d_sb;
35711+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
5527c038 35712+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) {
1facf9fc 35713+ err = link_or_create_wh(sb, bindex, wh_dentry);
076b876e 35714+ if (!err) {
1facf9fc 35715+ au_set_dbwh(dentry, bindex);
076b876e
AM
35716+ au_fhsm_wrote(sb, bindex, /*force*/0);
35717+ } else {
1facf9fc 35718+ dput(wh_dentry);
35719+ wh_dentry = ERR_PTR(err);
35720+ }
35721+ }
35722+
35723+ return wh_dentry;
35724+}
35725+
35726+/* ---------------------------------------------------------------------- */
35727+
35728+/* Delete all whiteouts in this directory on branch bindex. */
35729+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
35730+ aufs_bindex_t bindex, struct au_branch *br)
35731+{
35732+ int err;
35733+ unsigned long ul, n;
35734+ struct qstr wh_name;
35735+ char *p;
35736+ struct hlist_head *head;
c06a8ce3 35737+ struct au_vdir_wh *pos;
1facf9fc 35738+ struct au_vdir_destr *str;
35739+
35740+ err = -ENOMEM;
537831f9 35741+ p = (void *)__get_free_page(GFP_NOFS);
1facf9fc 35742+ wh_name.name = p;
35743+ if (unlikely(!wh_name.name))
35744+ goto out;
35745+
35746+ err = 0;
35747+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
35748+ p += AUFS_WH_PFX_LEN;
35749+ n = whlist->nh_num;
35750+ head = whlist->nh_head;
35751+ for (ul = 0; !err && ul < n; ul++, head++) {
c06a8ce3
AM
35752+ hlist_for_each_entry(pos, head, wh_hash) {
35753+ if (pos->wh_bindex != bindex)
1facf9fc 35754+ continue;
35755+
c06a8ce3 35756+ str = &pos->wh_str;
1facf9fc 35757+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
35758+ memcpy(p, str->name, str->len);
35759+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
35760+ err = unlink_wh_name(h_dentry, &wh_name, br);
35761+ if (!err)
35762+ continue;
35763+ break;
35764+ }
35765+ AuIOErr("whiteout name too long %.*s\n",
35766+ str->len, str->name);
35767+ err = -EIO;
35768+ break;
35769+ }
35770+ }
1c60b727 35771+ free_page((unsigned long)wh_name.name);
1facf9fc 35772+
4f0767ce 35773+out:
1facf9fc 35774+ return err;
35775+}
35776+
35777+struct del_wh_children_args {
35778+ int *errp;
35779+ struct dentry *h_dentry;
1308ab2a 35780+ struct au_nhash *whlist;
1facf9fc 35781+ aufs_bindex_t bindex;
35782+ struct au_branch *br;
35783+};
35784+
35785+static void call_del_wh_children(void *args)
35786+{
35787+ struct del_wh_children_args *a = args;
1308ab2a 35788+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 35789+}
35790+
35791+/* ---------------------------------------------------------------------- */
35792+
35793+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
35794+{
35795+ struct au_whtmp_rmdir *whtmp;
dece6358 35796+ int err;
1308ab2a 35797+ unsigned int rdhash;
dece6358
AM
35798+
35799+ SiMustAnyLock(sb);
1facf9fc 35800+
be52b249 35801+ whtmp = kzalloc(sizeof(*whtmp), gfp);
dece6358
AM
35802+ if (unlikely(!whtmp)) {
35803+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 35804+ goto out;
dece6358 35805+ }
1facf9fc 35806+
1308ab2a 35807+ /* no estimation for dir size */
35808+ rdhash = au_sbi(sb)->si_rdhash;
35809+ if (!rdhash)
35810+ rdhash = AUFS_RDHASH_DEF;
35811+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
35812+ if (unlikely(err)) {
9f237c51 35813+ au_kfree_rcu(whtmp);
1308ab2a 35814+ whtmp = ERR_PTR(err);
35815+ }
dece6358 35816+
4f0767ce 35817+out:
dece6358 35818+ return whtmp;
1facf9fc 35819+}
35820+
35821+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
35822+{
027c5e7a 35823+ if (whtmp->br)
acd2b654 35824+ au_lcnt_dec(&whtmp->br->br_count);
1facf9fc 35825+ dput(whtmp->wh_dentry);
35826+ iput(whtmp->dir);
dece6358 35827+ au_nhash_wh_free(&whtmp->whlist);
9f237c51 35828+ au_kfree_rcu(whtmp);
1facf9fc 35829+}
35830+
35831+/*
35832+ * rmdir the whiteouted temporary named dir @h_dentry.
35833+ * @whlist: whiteouted children.
35834+ */
35835+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
35836+ struct dentry *wh_dentry, struct au_nhash *whlist)
35837+{
35838+ int err;
2000de60 35839+ unsigned int h_nlink;
1facf9fc 35840+ struct path h_tmp;
35841+ struct inode *wh_inode, *h_dir;
35842+ struct au_branch *br;
35843+
5527c038 35844+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
1facf9fc 35845+ IMustLock(h_dir);
35846+
35847+ br = au_sbr(dir->i_sb, bindex);
5527c038 35848+ wh_inode = d_inode(wh_dentry);
febd17d6 35849+ inode_lock_nested(wh_inode, AuLsc_I_CHILD);
1facf9fc 35850+
35851+ /*
35852+ * someone else might change some whiteouts while we were sleeping.
35853+ * it means this whlist may have an obsoleted entry.
35854+ */
35855+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
35856+ err = del_wh_children(wh_dentry, whlist, bindex, br);
35857+ else {
35858+ int wkq_err;
35859+ struct del_wh_children_args args = {
35860+ .errp = &err,
35861+ .h_dentry = wh_dentry,
1308ab2a 35862+ .whlist = whlist,
1facf9fc 35863+ .bindex = bindex,
35864+ .br = br
35865+ };
35866+
35867+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
35868+ if (unlikely(wkq_err))
35869+ err = wkq_err;
35870+ }
febd17d6 35871+ inode_unlock(wh_inode);
1facf9fc 35872+
35873+ if (!err) {
35874+ h_tmp.dentry = wh_dentry;
86dc4139 35875+ h_tmp.mnt = au_br_mnt(br);
2000de60 35876+ h_nlink = h_dir->i_nlink;
1facf9fc 35877+ err = vfsub_rmdir(h_dir, &h_tmp);
2000de60
JR
35878+ /* some fs doesn't change the parent nlink in some cases */
35879+ h_nlink -= h_dir->i_nlink;
1facf9fc 35880+ }
35881+
35882+ if (!err) {
5afbbe0d 35883+ if (au_ibtop(dir) == bindex) {
7f207e10 35884+ /* todo: dir->i_mutex is necessary */
1facf9fc 35885+ au_cpup_attr_timesizes(dir);
2000de60
JR
35886+ if (h_nlink)
35887+ vfsub_drop_nlink(dir);
1facf9fc 35888+ }
35889+ return 0; /* success */
35890+ }
35891+
523b37e3 35892+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err);
1facf9fc 35893+ return err;
35894+}
35895+
35896+static void call_rmdir_whtmp(void *args)
35897+{
35898+ int err;
e49829fe 35899+ aufs_bindex_t bindex;
1facf9fc 35900+ struct au_whtmp_rmdir *a = args;
35901+ struct super_block *sb;
35902+ struct dentry *h_parent;
35903+ struct inode *h_dir;
1facf9fc 35904+ struct au_hinode *hdir;
35905+
35906+ /* rmdir by nfsd may cause deadlock with this i_mutex */
febd17d6 35907+ /* inode_lock(a->dir); */
e49829fe 35908+ err = -EROFS;
1facf9fc 35909+ sb = a->dir->i_sb;
e49829fe
JR
35910+ si_read_lock(sb, !AuLock_FLUSH);
35911+ if (!au_br_writable(a->br->br_perm))
35912+ goto out;
35913+ bindex = au_br_index(sb, a->br->br_id);
35914+ if (unlikely(bindex < 0))
1facf9fc 35915+ goto out;
35916+
35917+ err = -EIO;
1facf9fc 35918+ ii_write_lock_parent(a->dir);
35919+ h_parent = dget_parent(a->wh_dentry);
5527c038 35920+ h_dir = d_inode(h_parent);
e49829fe 35921+ hdir = au_hi(a->dir, bindex);
86dc4139
AM
35922+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
35923+ if (unlikely(err))
35924+ goto out_mnt;
5afbbe0d 35925+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
35926+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
35927+ a->br);
86dc4139
AM
35928+ if (!err)
35929+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist);
5afbbe0d 35930+ au_hn_inode_unlock(hdir);
86dc4139
AM
35931+ vfsub_mnt_drop_write(au_br_mnt(a->br));
35932+
35933+out_mnt:
1facf9fc 35934+ dput(h_parent);
35935+ ii_write_unlock(a->dir);
4f0767ce 35936+out:
febd17d6 35937+ /* inode_unlock(a->dir); */
1facf9fc 35938+ au_whtmp_rmdir_free(a);
027c5e7a
AM
35939+ si_read_unlock(sb);
35940+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 35941+ if (unlikely(err))
35942+ AuIOErr("err %d\n", err);
35943+}
35944+
35945+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
35946+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
35947+{
35948+ int wkq_err;
e49829fe 35949+ struct super_block *sb;
1facf9fc 35950+
35951+ IMustLock(dir);
35952+
35953+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 35954+ sb = dir->i_sb;
1facf9fc 35955+ args->dir = au_igrab(dir);
e49829fe 35956+ args->br = au_sbr(sb, bindex);
acd2b654 35957+ au_lcnt_inc(&args->br->br_count);
1facf9fc 35958+ args->wh_dentry = dget(wh_dentry);
53392da6 35959+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 35960+ if (unlikely(wkq_err)) {
523b37e3 35961+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err);
1facf9fc 35962+ au_whtmp_rmdir_free(args);
35963+ }
35964+}
7f207e10 35965diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
eca34b5c
AM
35966--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
35967+++ linux/fs/aufs/whout.h 2019-07-11 15:42:14.475571481 +0200
062440b3
AM
35968@@ -0,0 +1,86 @@
35969+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 35970+/*
ba1aed25 35971+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 35972+ *
35973+ * This program, aufs is free software; you can redistribute it and/or modify
35974+ * it under the terms of the GNU General Public License as published by
35975+ * the Free Software Foundation; either version 2 of the License, or
35976+ * (at your option) any later version.
dece6358
AM
35977+ *
35978+ * This program is distributed in the hope that it will be useful,
35979+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35980+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35981+ * GNU General Public License for more details.
35982+ *
35983+ * You should have received a copy of the GNU General Public License
523b37e3 35984+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35985+ */
35986+
35987+/*
35988+ * whiteout for logical deletion and opaque directory
35989+ */
35990+
35991+#ifndef __AUFS_WHOUT_H__
35992+#define __AUFS_WHOUT_H__
35993+
35994+#ifdef __KERNEL__
35995+
1facf9fc 35996+#include "dir.h"
35997+
35998+/* whout.c */
35999+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
076b876e
AM
36000+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio);
36001+int au_diropq_test(struct dentry *h_dentry);
3c1bdaff 36002+struct au_branch;
1facf9fc 36003+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
36004+ struct qstr *prefix);
36005+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
36006+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
36007+ struct dentry *dentry);
86dc4139 36008+int au_wh_init(struct au_branch *br, struct super_block *sb);
1facf9fc 36009+
36010+/* diropq flags */
36011+#define AuDiropq_CREATE 1
36012+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
36013+#define au_fset_diropq(flags, name) \
36014+ do { (flags) |= AuDiropq_##name; } while (0)
36015+#define au_fclr_diropq(flags, name) \
36016+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 36017+
36018+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
36019+ unsigned int flags);
36020+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
36021+ struct au_branch *br);
36022+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
36023+ struct dentry *h_parent);
36024+
36025+/* real rmdir for the whiteout-ed dir */
36026+struct au_whtmp_rmdir {
36027+ struct inode *dir;
e49829fe 36028+ struct au_branch *br;
1facf9fc 36029+ struct dentry *wh_dentry;
dece6358 36030+ struct au_nhash whlist;
1facf9fc 36031+};
36032+
36033+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
36034+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
36035+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
36036+ struct dentry *wh_dentry, struct au_nhash *whlist);
36037+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
36038+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
36039+
36040+/* ---------------------------------------------------------------------- */
36041+
36042+static inline struct dentry *au_diropq_create(struct dentry *dentry,
36043+ aufs_bindex_t bindex)
36044+{
36045+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
36046+}
36047+
36048+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
36049+{
36050+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
36051+}
36052+
36053+#endif /* __KERNEL__ */
36054+#endif /* __AUFS_WHOUT_H__ */
7f207e10 36055diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
eca34b5c
AM
36056--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
36057+++ linux/fs/aufs/wkq.c 2019-07-11 15:42:14.475571481 +0200
acd2b654 36058@@ -0,0 +1,392 @@
cd7a4cd9 36059+// SPDX-License-Identifier: GPL-2.0
1facf9fc 36060+/*
ba1aed25 36061+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 36062+ *
36063+ * This program, aufs is free software; you can redistribute it and/or modify
36064+ * it under the terms of the GNU General Public License as published by
36065+ * the Free Software Foundation; either version 2 of the License, or
36066+ * (at your option) any later version.
dece6358
AM
36067+ *
36068+ * This program is distributed in the hope that it will be useful,
36069+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36070+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36071+ * GNU General Public License for more details.
36072+ *
36073+ * You should have received a copy of the GNU General Public License
523b37e3 36074+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36075+ */
36076+
36077+/*
36078+ * workqueue for asynchronous/super-io operations
acd2b654 36079+ * todo: try new credential scheme
1facf9fc 36080+ */
36081+
dece6358 36082+#include <linux/module.h>
1facf9fc 36083+#include "aufs.h"
36084+
9dbd164d 36085+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 36086+
9dbd164d 36087+static struct workqueue_struct *au_wkq;
1facf9fc 36088+
36089+struct au_wkinfo {
36090+ struct work_struct wk;
7f207e10 36091+ struct kobject *kobj;
1facf9fc 36092+
36093+ unsigned int flags; /* see wkq.h */
36094+
36095+ au_wkq_func_t func;
36096+ void *args;
36097+
8b6a4947
AM
36098+#ifdef CONFIG_LOCKDEP
36099+ int dont_check;
36100+ struct held_lock **hlock;
36101+#endif
36102+
1facf9fc 36103+ struct completion *comp;
36104+};
36105+
36106+/* ---------------------------------------------------------------------- */
8b6a4947
AM
36107+/*
36108+ * Aufs passes some operations to the workqueue such as the internal copyup.
36109+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the
36110+ * job run by workqueue depends upon the locks acquired in the other task.
36111+ * Delegating a small operation to the workqueue, aufs passes its lockdep
36112+ * information too. And the job in the workqueue restores the info in order to
36113+ * pretend as if it acquired those locks. This is just to make LOCKDEP work
36114+ * correctly and expectedly.
36115+ */
36116+
36117+#ifndef CONFIG_LOCKDEP
36118+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo);
36119+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo);
36120+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo);
36121+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo);
36122+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo);
36123+#else
36124+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo)
36125+{
36126+ wkinfo->hlock = NULL;
36127+ wkinfo->dont_check = 0;
36128+}
36129+
36130+/*
36131+ * 1: matched
36132+ * 0: unmatched
36133+ */
36134+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name)
36135+{
36136+ static DEFINE_SPINLOCK(spin);
36137+ static struct {
36138+ char *name;
36139+ struct lock_class_key *key;
36140+ } a[] = {
36141+ { .name = "&sbinfo->si_rwsem" },
36142+ { .name = "&finfo->fi_rwsem" },
36143+ { .name = "&dinfo->di_rwsem" },
36144+ { .name = "&iinfo->ii_rwsem" }
36145+ };
36146+ static int set;
36147+ int i;
36148+
36149+ /* lockless read from 'set.' see below */
36150+ if (set == ARRAY_SIZE(a)) {
36151+ for (i = 0; i < ARRAY_SIZE(a); i++)
36152+ if (a[i].key == key)
36153+ goto match;
36154+ goto unmatch;
36155+ }
36156+
36157+ spin_lock(&spin);
36158+ if (set)
36159+ for (i = 0; i < ARRAY_SIZE(a); i++)
36160+ if (a[i].key == key) {
36161+ spin_unlock(&spin);
36162+ goto match;
36163+ }
36164+ for (i = 0; i < ARRAY_SIZE(a); i++) {
36165+ if (a[i].key) {
36166+ if (unlikely(a[i].key == key)) { /* rare but possible */
36167+ spin_unlock(&spin);
36168+ goto match;
36169+ } else
36170+ continue;
36171+ }
36172+ if (strstr(a[i].name, name)) {
36173+ /*
36174+ * the order of these three lines is important for the
36175+ * lockless read above.
36176+ */
36177+ a[i].key = key;
36178+ spin_unlock(&spin);
36179+ set++;
36180+ /* AuDbg("%d, %s\n", set, name); */
36181+ goto match;
36182+ }
36183+ }
36184+ spin_unlock(&spin);
36185+ goto unmatch;
36186+
36187+match:
36188+ return 1;
36189+unmatch:
36190+ return 0;
36191+}
36192+
36193+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo)
36194+{
36195+ int err, n;
36196+ struct task_struct *curr;
36197+ struct held_lock **hl, *held_locks, *p;
36198+
36199+ err = 0;
36200+ curr = current;
36201+ wkinfo->dont_check = lockdep_recursing(curr);
36202+ if (wkinfo->dont_check)
36203+ goto out;
36204+ n = curr->lockdep_depth;
36205+ if (!n)
36206+ goto out;
36207+
36208+ err = -ENOMEM;
36209+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS);
36210+ if (unlikely(!wkinfo->hlock))
36211+ goto out;
36212+
36213+ err = 0;
36214+#if 0
36215+ if (0 && au_debug_test()) /* left for debugging */
36216+ lockdep_print_held_locks(curr);
36217+#endif
36218+ held_locks = curr->held_locks;
36219+ hl = wkinfo->hlock;
36220+ while (n--) {
36221+ p = held_locks++;
36222+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name))
36223+ *hl++ = p;
36224+ }
36225+ *hl = NULL;
36226+
36227+out:
36228+ return err;
36229+}
36230+
36231+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo)
36232+{
9f237c51 36233+ au_kfree_try_rcu(wkinfo->hlock);
8b6a4947
AM
36234+}
36235+
36236+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo)
36237+{
36238+ struct held_lock *p, **hl = wkinfo->hlock;
36239+ int subclass;
36240+
36241+ if (wkinfo->dont_check)
36242+ lockdep_off();
36243+ if (!hl)
36244+ return;
36245+ while ((p = *hl++)) { /* assignment */
36246+ subclass = lockdep_hlock_class(p)->subclass;
36247+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */
36248+ if (p->read)
36249+ rwsem_acquire_read(p->instance, subclass, 0,
36250+ /*p->acquire_ip*/_RET_IP_);
36251+ else
36252+ rwsem_acquire(p->instance, subclass, 0,
36253+ /*p->acquire_ip*/_RET_IP_);
36254+ }
36255+}
36256+
36257+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo)
36258+{
36259+ struct held_lock *p, **hl = wkinfo->hlock;
36260+
36261+ if (wkinfo->dont_check)
36262+ lockdep_on();
36263+ if (!hl)
36264+ return;
36265+ while ((p = *hl++)) /* assignment */
36266+ rwsem_release(p->instance, 0, /*p->acquire_ip*/_RET_IP_);
36267+}
36268+#endif
1facf9fc 36269+
1facf9fc 36270+static void wkq_func(struct work_struct *wk)
36271+{
36272+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
36273+
2dfbb274 36274+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
36275+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
36276+
8b6a4947 36277+ au_wkq_lockdep_pre(wkinfo);
1facf9fc 36278+ wkinfo->func(wkinfo->args);
8b6a4947 36279+ au_wkq_lockdep_post(wkinfo);
1facf9fc 36280+ if (au_ftest_wkq(wkinfo->flags, WAIT))
36281+ complete(wkinfo->comp);
36282+ else {
7f207e10 36283+ kobject_put(wkinfo->kobj);
9dbd164d 36284+ module_put(THIS_MODULE); /* todo: ?? */
9f237c51 36285+ au_kfree_rcu(wkinfo);
1facf9fc 36286+ }
36287+}
36288+
36289+/*
36290+ * Since struct completion is large, try allocating it dynamically.
36291+ */
c2b27bf2 36292+#if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */
1facf9fc 36293+#define AuWkqCompDeclare(name) struct completion *comp = NULL
36294+
36295+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
36296+{
36297+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
36298+ if (*comp) {
36299+ init_completion(*comp);
36300+ wkinfo->comp = *comp;
36301+ return 0;
36302+ }
36303+ return -ENOMEM;
36304+}
36305+
36306+static void au_wkq_comp_free(struct completion *comp)
36307+{
9f237c51 36308+ au_kfree_rcu(comp);
1facf9fc 36309+}
36310+
36311+#else
36312+
36313+/* no braces */
36314+#define AuWkqCompDeclare(name) \
36315+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
36316+ struct completion *comp = &_ ## name
36317+
36318+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
36319+{
36320+ wkinfo->comp = *comp;
36321+ return 0;
36322+}
36323+
36324+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
36325+{
36326+ /* empty */
36327+}
36328+#endif /* 4KSTACKS */
36329+
53392da6 36330+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 36331+{
53392da6
AM
36332+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
36333+ if (au_wkq_test()) {
38d290e6 36334+ AuWarn1("wkq from wkq, unless silly-rename on NFS,"
acd2b654
AM
36335+ " due to a dead dir by UDBA,"
36336+ " or async xino write?\n");
53392da6
AM
36337+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
36338+ }
36339+ } else
36340+ au_dbg_verify_kthread();
36341+
36342+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 36343+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 36344+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
36345+ } else {
36346+ INIT_WORK(&wkinfo->wk, wkq_func);
36347+ schedule_work(&wkinfo->wk);
36348+ }
1facf9fc 36349+}
36350+
7f207e10
AM
36351+/*
36352+ * Be careful. It is easy to make deadlock happen.
36353+ * processA: lock, wkq and wait
36354+ * processB: wkq and wait, lock in wkq
36355+ * --> deadlock
36356+ */
b752ccd1 36357+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 36358+{
36359+ int err;
36360+ AuWkqCompDeclare(comp);
36361+ struct au_wkinfo wkinfo = {
b752ccd1 36362+ .flags = flags,
1facf9fc 36363+ .func = func,
36364+ .args = args
36365+ };
36366+
36367+ err = au_wkq_comp_alloc(&wkinfo, &comp);
8b6a4947
AM
36368+ if (unlikely(err))
36369+ goto out;
36370+ err = au_wkq_lockdep_alloc(&wkinfo);
36371+ if (unlikely(err))
36372+ goto out_comp;
1facf9fc 36373+ if (!err) {
53392da6 36374+ au_wkq_run(&wkinfo);
1facf9fc 36375+ /* no timeout, no interrupt */
36376+ wait_for_completion(wkinfo.comp);
1facf9fc 36377+ }
8b6a4947 36378+ au_wkq_lockdep_free(&wkinfo);
1facf9fc 36379+
8b6a4947
AM
36380+out_comp:
36381+ au_wkq_comp_free(comp);
36382+out:
36383+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 36384+ return err;
1facf9fc 36385+}
36386+
027c5e7a
AM
36387+/*
36388+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
36389+ * problem in a concurrent umounting.
36390+ */
53392da6
AM
36391+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36392+ unsigned int flags)
1facf9fc 36393+{
36394+ int err;
36395+ struct au_wkinfo *wkinfo;
36396+
f0c0a007 36397+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
1facf9fc 36398+
36399+ /*
36400+ * wkq_func() must free this wkinfo.
36401+ * it highly depends upon the implementation of workqueue.
36402+ */
36403+ err = 0;
36404+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
36405+ if (wkinfo) {
7f207e10 36406+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 36407+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 36408+ wkinfo->func = func;
36409+ wkinfo->args = args;
36410+ wkinfo->comp = NULL;
8b6a4947 36411+ au_wkq_lockdep_init(wkinfo);
7f207e10 36412+ kobject_get(wkinfo->kobj);
9dbd164d 36413+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 36414+
53392da6 36415+ au_wkq_run(wkinfo);
1facf9fc 36416+ } else {
36417+ err = -ENOMEM;
e49829fe 36418+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 36419+ }
36420+
36421+ return err;
36422+}
36423+
36424+/* ---------------------------------------------------------------------- */
36425+
36426+void au_nwt_init(struct au_nowait_tasks *nwt)
36427+{
f0c0a007
AM
36428+ atomic_set(&nwt->nw_len, 0);
36429+ /* smp_mb(); */ /* atomic_set */
1facf9fc 36430+ init_waitqueue_head(&nwt->nw_wq);
36431+}
36432+
36433+void au_wkq_fin(void)
36434+{
9dbd164d 36435+ destroy_workqueue(au_wkq);
1facf9fc 36436+}
36437+
36438+int __init au_wkq_init(void)
36439+{
9dbd164d 36440+ int err;
b752ccd1
AM
36441+
36442+ err = 0;
86dc4139 36443+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE);
9dbd164d
AM
36444+ if (IS_ERR(au_wkq))
36445+ err = PTR_ERR(au_wkq);
36446+ else if (!au_wkq)
36447+ err = -ENOMEM;
b752ccd1
AM
36448+
36449+ return err;
1facf9fc 36450+}
7f207e10 36451diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
eca34b5c
AM
36452--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
36453+++ linux/fs/aufs/wkq.h 2019-07-11 15:42:14.475571481 +0200
acd2b654 36454@@ -0,0 +1,89 @@
062440b3 36455+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 36456+/*
ba1aed25 36457+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 36458+ *
36459+ * This program, aufs is free software; you can redistribute it and/or modify
36460+ * it under the terms of the GNU General Public License as published by
36461+ * the Free Software Foundation; either version 2 of the License, or
36462+ * (at your option) any later version.
dece6358
AM
36463+ *
36464+ * This program is distributed in the hope that it will be useful,
36465+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36466+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36467+ * GNU General Public License for more details.
36468+ *
36469+ * You should have received a copy of the GNU General Public License
523b37e3 36470+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36471+ */
36472+
36473+/*
36474+ * workqueue for asynchronous/super-io operations
36475+ * todo: try new credentials management scheme
36476+ */
36477+
36478+#ifndef __AUFS_WKQ_H__
36479+#define __AUFS_WKQ_H__
36480+
36481+#ifdef __KERNEL__
36482+
8b6a4947 36483+#include <linux/wait.h>
5afbbe0d 36484+
dece6358
AM
36485+struct super_block;
36486+
1facf9fc 36487+/* ---------------------------------------------------------------------- */
36488+
36489+/*
36490+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
36491+ */
36492+struct au_nowait_tasks {
f0c0a007 36493+ atomic_t nw_len;
1facf9fc 36494+ wait_queue_head_t nw_wq;
36495+};
36496+
36497+/* ---------------------------------------------------------------------- */
36498+
36499+typedef void (*au_wkq_func_t)(void *args);
36500+
36501+/* wkq flags */
36502+#define AuWkq_WAIT 1
9dbd164d 36503+#define AuWkq_NEST (1 << 1)
1facf9fc 36504+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
36505+#define au_fset_wkq(flags, name) \
36506+ do { (flags) |= AuWkq_##name; } while (0)
36507+#define au_fclr_wkq(flags, name) \
36508+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 36509+
36510+/* wkq.c */
b752ccd1 36511+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
36512+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36513+ unsigned int flags);
1facf9fc 36514+void au_nwt_init(struct au_nowait_tasks *nwt);
36515+int __init au_wkq_init(void);
36516+void au_wkq_fin(void);
36517+
36518+/* ---------------------------------------------------------------------- */
36519+
53392da6
AM
36520+static inline int au_wkq_test(void)
36521+{
36522+ return current->flags & PF_WQ_WORKER;
36523+}
36524+
b752ccd1 36525+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 36526+{
b752ccd1 36527+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 36528+}
36529+
36530+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
36531+{
f0c0a007 36532+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 36533+ wake_up_all(&nwt->nw_wq);
36534+}
36535+
36536+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
36537+{
f0c0a007 36538+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
1facf9fc 36539+ return 0;
36540+}
36541+
36542+#endif /* __KERNEL__ */
36543+#endif /* __AUFS_WKQ_H__ */
c1595e42 36544diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c
eca34b5c
AM
36545--- /usr/share/empty/fs/aufs/xattr.c 1970-01-01 01:00:00.000000000 +0100
36546+++ linux/fs/aufs/xattr.c 2019-07-11 15:42:14.475571481 +0200
062440b3 36547@@ -0,0 +1,356 @@
cd7a4cd9 36548+// SPDX-License-Identifier: GPL-2.0
c1595e42 36549+/*
ba1aed25 36550+ * Copyright (C) 2014-2019 Junjiro R. Okajima
c1595e42
JR
36551+ *
36552+ * This program, aufs is free software; you can redistribute it and/or modify
36553+ * it under the terms of the GNU General Public License as published by
36554+ * the Free Software Foundation; either version 2 of the License, or
36555+ * (at your option) any later version.
36556+ *
36557+ * This program is distributed in the hope that it will be useful,
36558+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36559+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36560+ * GNU General Public License for more details.
36561+ *
36562+ * You should have received a copy of the GNU General Public License
36563+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
36564+ */
36565+
36566+/*
36567+ * handling xattr functions
36568+ */
36569+
a2654f78
AM
36570+#include <linux/fs.h>
36571+#include <linux/posix_acl_xattr.h>
c1595e42
JR
36572+#include <linux/xattr.h>
36573+#include "aufs.h"
36574+
36575+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
36576+{
36577+ if (!ignore_flags)
36578+ goto out;
36579+ switch (err) {
36580+ case -ENOMEM:
36581+ case -EDQUOT:
36582+ goto out;
36583+ }
36584+
36585+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
36586+ err = 0;
36587+ goto out;
36588+ }
36589+
36590+#define cmp(brattr, prefix) do { \
36591+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \
36592+ XATTR_##prefix##_PREFIX_LEN)) { \
36593+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \
36594+ err = 0; \
36595+ goto out; \
36596+ } \
36597+ } while (0)
36598+
36599+ cmp(SEC, SECURITY);
36600+ cmp(SYS, SYSTEM);
36601+ cmp(TR, TRUSTED);
36602+ cmp(USR, USER);
36603+#undef cmp
36604+
36605+ if (ignore_flags & AuBrAttr_ICEX_OTH)
36606+ err = 0;
36607+
36608+out:
36609+ return err;
36610+}
36611+
36612+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
36613+
36614+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
7e9cd9fe
AM
36615+ char *name, char **buf, unsigned int ignore_flags,
36616+ unsigned int verbose)
c1595e42
JR
36617+{
36618+ int err;
36619+ ssize_t ssz;
36620+ struct inode *h_idst;
36621+
36622+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS);
36623+ err = ssz;
36624+ if (unlikely(err <= 0)) {
c1595e42
JR
36625+ if (err == -ENODATA
36626+ || (err == -EOPNOTSUPP
b912730e 36627+ && ((ignore_flags & au_xattr_out_of_list)
5527c038 36628+ || (au_test_nfs_noacl(d_inode(h_src))
b912730e
AM
36629+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
36630+ || !strcmp(name,
36631+ XATTR_NAME_POSIX_ACL_DEFAULT))))
36632+ ))
c1595e42 36633+ err = 0;
b912730e
AM
36634+ if (err && (verbose || au_debug_test()))
36635+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36636+ goto out;
36637+ }
36638+
36639+ /* unlock it temporary */
5527c038 36640+ h_idst = d_inode(h_dst);
febd17d6 36641+ inode_unlock(h_idst);
c1595e42 36642+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0);
febd17d6 36643+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42 36644+ if (unlikely(err)) {
7e9cd9fe
AM
36645+ if (verbose || au_debug_test())
36646+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36647+ err = au_xattr_ignore(err, name, ignore_flags);
36648+ }
36649+
36650+out:
36651+ return err;
36652+}
36653+
7e9cd9fe
AM
36654+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
36655+ unsigned int verbose)
c1595e42
JR
36656+{
36657+ int err, unlocked, acl_access, acl_default;
36658+ ssize_t ssz;
36659+ struct inode *h_isrc, *h_idst;
36660+ char *value, *p, *o, *e;
36661+
36662+ /* try stopping to update the source inode while we are referencing */
7e9cd9fe 36663+ /* there should not be the parent-child relationship between them */
5527c038
JR
36664+ h_isrc = d_inode(h_src);
36665+ h_idst = d_inode(h_dst);
febd17d6 36666+ inode_unlock(h_idst);
be118d29 36667+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD);
febd17d6 36668+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42
JR
36669+ unlocked = 0;
36670+
36671+ /* some filesystems don't list POSIX ACL, for example tmpfs */
36672+ ssz = vfs_listxattr(h_src, NULL, 0);
36673+ err = ssz;
36674+ if (unlikely(err < 0)) {
36675+ AuTraceErr(err);
36676+ if (err == -ENODATA
36677+ || err == -EOPNOTSUPP)
36678+ err = 0; /* ignore */
36679+ goto out;
36680+ }
36681+
36682+ err = 0;
36683+ p = NULL;
36684+ o = NULL;
36685+ if (ssz) {
36686+ err = -ENOMEM;
36687+ p = kmalloc(ssz, GFP_NOFS);
36688+ o = p;
36689+ if (unlikely(!p))
36690+ goto out;
36691+ err = vfs_listxattr(h_src, p, ssz);
36692+ }
3c1bdaff 36693+ inode_unlock_shared(h_isrc);
c1595e42
JR
36694+ unlocked = 1;
36695+ AuDbg("err %d, ssz %zd\n", err, ssz);
36696+ if (unlikely(err < 0))
36697+ goto out_free;
36698+
36699+ err = 0;
36700+ e = p + ssz;
36701+ value = NULL;
36702+ acl_access = 0;
36703+ acl_default = 0;
36704+ while (!err && p < e) {
36705+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
36706+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
36707+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
36708+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
36709+ - 1);
7e9cd9fe
AM
36710+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
36711+ verbose);
c1595e42
JR
36712+ p += strlen(p) + 1;
36713+ }
36714+ AuTraceErr(err);
36715+ ignore_flags |= au_xattr_out_of_list;
36716+ if (!err && !acl_access) {
36717+ err = au_do_cpup_xattr(h_dst, h_src,
36718+ XATTR_NAME_POSIX_ACL_ACCESS, &value,
7e9cd9fe 36719+ ignore_flags, verbose);
c1595e42
JR
36720+ AuTraceErr(err);
36721+ }
36722+ if (!err && !acl_default) {
36723+ err = au_do_cpup_xattr(h_dst, h_src,
36724+ XATTR_NAME_POSIX_ACL_DEFAULT, &value,
7e9cd9fe 36725+ ignore_flags, verbose);
c1595e42
JR
36726+ AuTraceErr(err);
36727+ }
36728+
9f237c51 36729+ au_kfree_try_rcu(value);
c1595e42
JR
36730+
36731+out_free:
9f237c51 36732+ au_kfree_try_rcu(o);
c1595e42
JR
36733+out:
36734+ if (!unlocked)
3c1bdaff 36735+ inode_unlock_shared(h_isrc);
c1595e42
JR
36736+ AuTraceErr(err);
36737+ return err;
36738+}
36739+
36740+/* ---------------------------------------------------------------------- */
36741+
a2654f78
AM
36742+static int au_smack_reentering(struct super_block *sb)
36743+{
36744+#if IS_ENABLED(CONFIG_SECURITY_SMACK)
36745+ /*
36746+ * as a part of lookup, smack_d_instantiate() is called, and it calls
36747+ * i_op->getxattr(). ouch.
36748+ */
36749+ return si_pid_test(sb);
36750+#else
36751+ return 0;
36752+#endif
36753+}
36754+
c1595e42
JR
36755+enum {
36756+ AU_XATTR_LIST,
36757+ AU_XATTR_GET
36758+};
36759+
36760+struct au_lgxattr {
36761+ int type;
36762+ union {
36763+ struct {
36764+ char *list;
36765+ size_t size;
36766+ } list;
36767+ struct {
36768+ const char *name;
36769+ void *value;
36770+ size_t size;
36771+ } get;
36772+ } u;
36773+};
36774+
36775+static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg)
36776+{
36777+ ssize_t err;
a2654f78 36778+ int reenter;
c1595e42
JR
36779+ struct path h_path;
36780+ struct super_block *sb;
36781+
36782+ sb = dentry->d_sb;
a2654f78
AM
36783+ reenter = au_smack_reentering(sb);
36784+ if (!reenter) {
36785+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
36786+ if (unlikely(err))
36787+ goto out;
36788+ }
36789+ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter);
c1595e42
JR
36790+ if (unlikely(err))
36791+ goto out_si;
36792+ if (unlikely(!h_path.dentry))
36793+ /* illegally overlapped or something */
36794+ goto out_di; /* pretending success */
36795+
36796+ /* always topmost entry only */
36797+ switch (arg->type) {
36798+ case AU_XATTR_LIST:
36799+ err = vfs_listxattr(h_path.dentry,
36800+ arg->u.list.list, arg->u.list.size);
36801+ break;
36802+ case AU_XATTR_GET:
5afbbe0d 36803+ AuDebugOn(d_is_negative(h_path.dentry));
c1595e42
JR
36804+ err = vfs_getxattr(h_path.dentry,
36805+ arg->u.get.name, arg->u.get.value,
36806+ arg->u.get.size);
36807+ break;
36808+ }
36809+
36810+out_di:
a2654f78
AM
36811+ if (!reenter)
36812+ di_read_unlock(dentry, AuLock_IR);
c1595e42 36813+out_si:
a2654f78
AM
36814+ if (!reenter)
36815+ si_read_unlock(sb);
c1595e42
JR
36816+out:
36817+ AuTraceErr(err);
36818+ return err;
36819+}
36820+
36821+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
36822+{
36823+ struct au_lgxattr arg = {
36824+ .type = AU_XATTR_LIST,
36825+ .u.list = {
36826+ .list = list,
36827+ .size = size
36828+ },
36829+ };
36830+
36831+ return au_lgxattr(dentry, &arg);
36832+}
36833+
f2c43d5f
AM
36834+static ssize_t au_getxattr(struct dentry *dentry,
36835+ struct inode *inode __maybe_unused,
36836+ const char *name, void *value, size_t size)
c1595e42
JR
36837+{
36838+ struct au_lgxattr arg = {
36839+ .type = AU_XATTR_GET,
36840+ .u.get = {
36841+ .name = name,
36842+ .value = value,
36843+ .size = size
36844+ },
36845+ };
36846+
36847+ return au_lgxattr(dentry, &arg);
36848+}
36849+
f2c43d5f
AM
36850+static int au_setxattr(struct dentry *dentry, struct inode *inode,
36851+ const char *name, const void *value, size_t size,
36852+ int flags)
c1595e42 36853+{
f2c43d5f 36854+ struct au_sxattr arg = {
c1595e42
JR
36855+ .type = AU_XATTR_SET,
36856+ .u.set = {
36857+ .name = name,
36858+ .value = value,
36859+ .size = size,
36860+ .flags = flags
36861+ },
36862+ };
36863+
f2c43d5f 36864+ return au_sxattr(dentry, inode, &arg);
c1595e42
JR
36865+}
36866+
36867+/* ---------------------------------------------------------------------- */
36868+
f2c43d5f
AM
36869+static int au_xattr_get(const struct xattr_handler *handler,
36870+ struct dentry *dentry, struct inode *inode,
36871+ const char *name, void *buffer, size_t size)
c1595e42 36872+{
f2c43d5f 36873+ return au_getxattr(dentry, inode, name, buffer, size);
c1595e42
JR
36874+}
36875+
f2c43d5f
AM
36876+static int au_xattr_set(const struct xattr_handler *handler,
36877+ struct dentry *dentry, struct inode *inode,
36878+ const char *name, const void *value, size_t size,
36879+ int flags)
c1595e42 36880+{
f2c43d5f 36881+ return au_setxattr(dentry, inode, name, value, size, flags);
c1595e42
JR
36882+}
36883+
36884+static const struct xattr_handler au_xattr_handler = {
f2c43d5f
AM
36885+ .name = "",
36886+ .prefix = "",
c1595e42
JR
36887+ .get = au_xattr_get,
36888+ .set = au_xattr_set
c1595e42
JR
36889+};
36890+
36891+static const struct xattr_handler *au_xattr_handlers[] = {
a2654f78
AM
36892+#ifdef CONFIG_FS_POSIX_ACL
36893+ &posix_acl_access_xattr_handler,
36894+ &posix_acl_default_xattr_handler,
36895+#endif
36896+ &au_xattr_handler, /* must be last */
f2c43d5f 36897+ NULL
c1595e42
JR
36898+};
36899+
36900+void au_xattr_init(struct super_block *sb)
36901+{
f2c43d5f 36902+ sb->s_xattr = au_xattr_handlers;
c1595e42 36903+}
7f207e10 36904diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
eca34b5c
AM
36905--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
36906+++ linux/fs/aufs/xino.c 2019-07-11 15:42:14.475571481 +0200
83b672a5 36907@@ -0,0 +1,1965 @@
cd7a4cd9 36908+// SPDX-License-Identifier: GPL-2.0
1facf9fc 36909+/*
ba1aed25 36910+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 36911+ *
36912+ * This program, aufs is free software; you can redistribute it and/or modify
36913+ * it under the terms of the GNU General Public License as published by
36914+ * the Free Software Foundation; either version 2 of the License, or
36915+ * (at your option) any later version.
dece6358
AM
36916+ *
36917+ * This program is distributed in the hope that it will be useful,
36918+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36919+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36920+ * GNU General Public License for more details.
36921+ *
36922+ * You should have received a copy of the GNU General Public License
523b37e3 36923+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36924+ */
36925+
36926+/*
36927+ * external inode number translation table and bitmap
062440b3
AM
36928+ *
36929+ * things to consider
36930+ * - the lifetime
36931+ * + au_xino object
36932+ * + XINO files (xino, xib, xigen)
36933+ * + dynamic debugfs entries (xiN)
36934+ * + static debugfs entries (xib, xigen)
36935+ * + static sysfs entry (xi_path)
36936+ * - several entry points to handle them.
36937+ * + mount(2) without xino option (default)
36938+ * + mount(2) with xino option
36939+ * + mount(2) with noxino option
36940+ * + umount(2)
36941+ * + remount with add/del branches
36942+ * + remount with xino/noxino options
1facf9fc 36943+ */
36944+
36945+#include <linux/seq_file.h>
392086de 36946+#include <linux/statfs.h>
1facf9fc 36947+#include "aufs.h"
36948+
062440b3
AM
36949+static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop,
36950+ aufs_bindex_t bbot,
36951+ struct super_block *h_sb)
1facf9fc 36952+{
062440b3
AM
36953+ /* todo: try binary-search if the branches are many */
36954+ for (; btop <= bbot; btop++)
36955+ if (h_sb == au_sbr_sb(sb, btop))
36956+ return btop;
36957+ return -1;
be52b249
AM
36958+}
36959+
062440b3
AM
36960+/*
36961+ * find another branch who is on the same filesystem of the specified
36962+ * branch{@btgt}. search until @bbot.
36963+ */
36964+static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
36965+ aufs_bindex_t bbot)
1facf9fc 36966+{
062440b3
AM
36967+ aufs_bindex_t bindex;
36968+ struct super_block *tgt_sb;
1facf9fc 36969+
062440b3
AM
36970+ tgt_sb = au_sbr_sb(sb, btgt);
36971+ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb);
36972+ if (bindex < 0)
36973+ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb);
1facf9fc 36974+
062440b3 36975+ return bindex;
1facf9fc 36976+}
36977+
36978+/* ---------------------------------------------------------------------- */
36979+
36980+/*
062440b3 36981+ * stop unnecessary notify events at creating xino files
1facf9fc 36982+ */
acd2b654
AM
36983+
36984+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry)
36985+{
36986+ aufs_bindex_t bfound, bindex, bbot;
36987+ struct dentry *parent;
36988+ struct au_branch *br;
36989+
36990+ bfound = -1;
36991+ parent = dentry->d_parent; /* safe d_parent access */
36992+ bbot = au_sbbot(sb);
36993+ for (bindex = 0; bindex <= bbot; bindex++) {
36994+ br = au_sbr(sb, bindex);
36995+ if (au_br_dentry(br) == parent) {
36996+ bfound = bindex;
36997+ break;
36998+ }
36999+ }
37000+
37001+ AuDbg("bfound b%d\n", bfound);
37002+ return bfound;
37003+}
37004+
062440b3
AM
37005+struct au_xino_lock_dir {
37006+ struct au_hinode *hdir;
37007+ struct dentry *parent;
37008+ struct inode *dir;
37009+};
37010+
37011+static struct dentry *au_dget_parent_lock(struct dentry *dentry,
37012+ unsigned int lsc)
1facf9fc 37013+{
062440b3
AM
37014+ struct dentry *parent;
37015+ struct inode *dir;
1facf9fc 37016+
062440b3 37017+ parent = dget_parent(dentry);
5527c038 37018+ dir = d_inode(parent);
062440b3
AM
37019+ inode_lock_nested(dir, lsc);
37020+#if 0 /* it should not happen */
37021+ spin_lock(&dentry->d_lock);
37022+ if (unlikely(dentry->d_parent != parent)) {
37023+ spin_unlock(&dentry->d_lock);
37024+ inode_unlock(dir);
37025+ dput(parent);
37026+ parent = NULL;
1facf9fc 37027+ goto out;
37028+ }
062440b3 37029+ spin_unlock(&dentry->d_lock);
1facf9fc 37030+
4f0767ce 37031+out:
062440b3
AM
37032+#endif
37033+ return parent;
1facf9fc 37034+}
37035+
062440b3 37036+static void au_xino_lock_dir(struct super_block *sb, struct path *xipath,
1facf9fc 37037+ struct au_xino_lock_dir *ldir)
37038+{
acd2b654 37039+ aufs_bindex_t bindex;
1facf9fc 37040+
37041+ ldir->hdir = NULL;
acd2b654 37042+ bindex = au_xi_root(sb, xipath->dentry);
1facf9fc 37043+ if (bindex >= 0) {
062440b3 37044+ /* rw branch root */
5527c038 37045+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 37046+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 37047+ } else {
062440b3
AM
37048+ /* other */
37049+ ldir->parent = au_dget_parent_lock(xipath->dentry,
37050+ AuLsc_I_PARENT);
febd17d6 37051+ ldir->dir = d_inode(ldir->parent);
1facf9fc 37052+ }
37053+}
37054+
37055+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
37056+{
37057+ if (ldir->hdir)
5afbbe0d 37058+ au_hn_inode_unlock(ldir->hdir);
1facf9fc 37059+ else {
febd17d6 37060+ inode_unlock(ldir->dir);
1facf9fc 37061+ dput(ldir->parent);
37062+ }
37063+}
37064+
37065+/* ---------------------------------------------------------------------- */
37066+
062440b3
AM
37067+/*
37068+ * create and set a new xino file
37069+ */
83b672a5
AM
37070+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
37071+ int wbrtop)
062440b3
AM
37072+{
37073+ struct file *file;
37074+ struct dentry *h_parent, *d;
37075+ struct inode *h_dir, *inode;
37076+ int err;
83b672a5 37077+ static DEFINE_MUTEX(mtx);
062440b3
AM
37078+
37079+ /*
37080+ * at mount-time, and the xino file is the default path,
37081+ * hnotify is disabled so we have no notify events to ignore.
37082+ * when a user specified the xino, we cannot get au_hdir to be ignored.
37083+ */
83b672a5
AM
37084+ if (!wbrtop)
37085+ mutex_lock(&mtx);
062440b3
AM
37086+ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
37087+ /* | __FMODE_NONOTIFY */,
cd7a4cd9 37088+ 0666);
062440b3 37089+ if (IS_ERR(file)) {
83b672a5
AM
37090+ if (!wbrtop)
37091+ mutex_unlock(&mtx);
062440b3
AM
37092+ if (!silent)
37093+ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file));
37094+ return file;
37095+ }
37096+
37097+ /* keep file count */
37098+ err = 0;
37099+ d = file->f_path.dentry;
37100+ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT);
83b672a5
AM
37101+ if (!wbrtop)
37102+ mutex_unlock(&mtx);
062440b3
AM
37103+ /* mnt_want_write() is unnecessary here */
37104+ h_dir = d_inode(h_parent);
37105+ inode = file_inode(file);
37106+ /* no delegation since it is just created */
37107+ if (inode->i_nlink)
37108+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL,
37109+ /*force*/0);
37110+ inode_unlock(h_dir);
37111+ dput(h_parent);
37112+ if (unlikely(err)) {
37113+ if (!silent)
37114+ pr_err("unlink %s(%d)\n", fpath, err);
37115+ goto out;
37116+ }
37117+
37118+ err = -EINVAL;
37119+ if (unlikely(sb == d->d_sb)) {
37120+ if (!silent)
37121+ pr_err("%s must be outside\n", fpath);
37122+ goto out;
37123+ }
37124+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
37125+ if (!silent)
37126+ pr_err("xino doesn't support %s(%s)\n",
37127+ fpath, au_sbtype(d->d_sb));
37128+ goto out;
37129+ }
37130+ return file; /* success */
37131+
37132+out:
37133+ fput(file);
37134+ file = ERR_PTR(err);
37135+ return file;
37136+}
37137+
37138+/*
37139+ * create a new xinofile at the same place/path as @base.
37140+ */
37141+struct file *au_xino_create2(struct super_block *sb, struct path *base,
37142+ struct file *copy_src)
37143+{
37144+ struct file *file;
37145+ struct dentry *dentry, *parent;
37146+ struct inode *dir, *delegated;
37147+ struct qstr *name;
37148+ struct path path;
37149+ int err, do_unlock;
37150+ struct au_xino_lock_dir ldir;
37151+
37152+ do_unlock = 1;
37153+ au_xino_lock_dir(sb, base, &ldir);
37154+ dentry = base->dentry;
37155+ parent = dentry->d_parent; /* dir inode is locked */
37156+ dir = d_inode(parent);
37157+ IMustLock(dir);
37158+
37159+ name = &dentry->d_name;
37160+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
37161+ if (IS_ERR(path.dentry)) {
37162+ file = (void *)path.dentry;
37163+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry));
37164+ goto out;
37165+ }
37166+
37167+ /* no need to mnt_want_write() since we call dentry_open() later */
cd7a4cd9 37168+ err = vfs_create(dir, path.dentry, 0666, NULL);
062440b3
AM
37169+ if (unlikely(err)) {
37170+ file = ERR_PTR(err);
37171+ pr_err("%pd create err %d\n", dentry, err);
37172+ goto out_dput;
37173+ }
37174+
37175+ path.mnt = base->mnt;
37176+ file = vfsub_dentry_open(&path,
37177+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
37178+ /* | __FMODE_NONOTIFY */);
37179+ if (IS_ERR(file)) {
37180+ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file));
37181+ goto out_dput;
37182+ }
37183+
37184+ delegated = NULL;
37185+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0);
37186+ au_xino_unlock_dir(&ldir);
37187+ do_unlock = 0;
37188+ if (unlikely(err == -EWOULDBLOCK)) {
37189+ pr_warn("cannot retry for NFSv4 delegation"
37190+ " for an internal unlink\n");
37191+ iput(delegated);
37192+ }
37193+ if (unlikely(err)) {
37194+ pr_err("%pd unlink err %d\n", dentry, err);
37195+ goto out_fput;
37196+ }
37197+
37198+ if (copy_src) {
37199+ /* no one can touch copy_src xino */
37200+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src));
37201+ if (unlikely(err)) {
37202+ pr_err("%pd copy err %d\n", dentry, err);
37203+ goto out_fput;
37204+ }
37205+ }
37206+ goto out_dput; /* success */
1facf9fc 37207+
062440b3
AM
37208+out_fput:
37209+ fput(file);
37210+ file = ERR_PTR(err);
37211+out_dput:
37212+ dput(path.dentry);
37213+out:
37214+ if (do_unlock)
37215+ au_xino_unlock_dir(&ldir);
37216+ return file;
37217+}
37218+
acd2b654
AM
37219+struct file *au_xino_file1(struct au_xino *xi)
37220+{
37221+ struct file *file;
37222+ unsigned int u, nfile;
37223+
37224+ file = NULL;
37225+ nfile = xi->xi_nfile;
37226+ for (u = 0; u < nfile; u++) {
37227+ file = xi->xi_file[u];
37228+ if (file)
37229+ break;
37230+ }
37231+
37232+ return file;
37233+}
37234+
37235+static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file)
37236+{
37237+ int err;
37238+ struct file *f;
37239+ void *p;
37240+
37241+ if (file)
37242+ get_file(file);
37243+
37244+ err = 0;
37245+ f = NULL;
37246+ if (idx < xi->xi_nfile) {
37247+ f = xi->xi_file[idx];
37248+ if (f)
37249+ fput(f);
37250+ } else {
37251+ p = au_kzrealloc(xi->xi_file,
37252+ sizeof(*xi->xi_file) * xi->xi_nfile,
37253+ sizeof(*xi->xi_file) * (idx + 1),
37254+ GFP_NOFS, /*may_shrink*/0);
37255+ if (p) {
37256+ MtxMustLock(&xi->xi_mtx);
37257+ xi->xi_file = p;
37258+ xi->xi_nfile = idx + 1;
37259+ } else {
37260+ err = -ENOMEM;
37261+ if (file)
37262+ fput(file);
37263+ goto out;
37264+ }
37265+ }
37266+ xi->xi_file[idx] = file;
37267+
37268+out:
37269+ return err;
37270+}
37271+
37272+/*
37273+ * if @xinew->xi is not set, then create new xigen file.
37274+ */
37275+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew)
37276+{
37277+ struct file *file;
37278+ int err;
37279+
37280+ SiMustAnyLock(sb);
37281+
37282+ file = au_xino_create2(sb, xinew->base, xinew->copy_src);
37283+ if (IS_ERR(file)) {
37284+ err = PTR_ERR(file);
37285+ pr_err("%s[%d], err %d\n",
37286+ xinew->xi ? "xino" : "xigen",
37287+ xinew->idx, err);
37288+ goto out;
37289+ }
37290+
37291+ if (xinew->xi)
37292+ err = au_xino_file_set(xinew->xi, xinew->idx, file);
37293+ else {
37294+ BUG();
37295+ /* todo: make xigen file an array */
37296+ /* err = au_xigen_file_set(sb, xinew->idx, file); */
37297+ }
37298+ fput(file);
37299+ if (unlikely(err))
37300+ file = ERR_PTR(err);
37301+
37302+out:
37303+ return file;
37304+}
37305+
062440b3
AM
37306+/* ---------------------------------------------------------------------- */
37307+
37308+/*
37309+ * truncate xino files
37310+ */
acd2b654
AM
37311+static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex,
37312+ int idx, struct kstatfs *st)
1facf9fc 37313+{
37314+ int err;
392086de 37315+ blkcnt_t blocks;
acd2b654
AM
37316+ struct file *file, *new_xino;
37317+ struct au_xi_new xinew = {
37318+ .idx = idx
37319+ };
37320+
37321+ err = 0;
37322+ xinew.xi = au_sbr(sb, bindex)->br_xino;
37323+ file = au_xino_file(xinew.xi, idx);
37324+ if (!file)
37325+ goto out;
37326+
37327+ xinew.base = &file->f_path;
37328+ err = vfs_statfs(xinew.base, st);
37329+ if (unlikely(err)) {
37330+ AuErr1("statfs err %d, ignored\n", err);
37331+ err = 0;
37332+ goto out;
37333+ }
37334+
37335+ blocks = file_inode(file)->i_blocks;
37336+ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37337+ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks);
37338+
37339+ xinew.copy_src = file;
37340+ new_xino = au_xi_new(sb, &xinew);
37341+ if (IS_ERR(new_xino)) {
37342+ err = PTR_ERR(new_xino);
37343+ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err);
37344+ goto out;
37345+ }
37346+
37347+ err = vfs_statfs(&new_xino->f_path, st);
37348+ if (!err)
37349+ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37350+ bindex, idx, (u64)file_inode(new_xino)->i_blocks,
37351+ st->f_bfree, st->f_blocks);
37352+ else {
37353+ AuErr1("statfs err %d, ignored\n", err);
37354+ err = 0;
37355+ }
37356+
37357+out:
37358+ return err;
37359+}
37360+
37361+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin)
37362+{
37363+ int err, i;
37364+ unsigned long jiffy;
062440b3 37365+ aufs_bindex_t bbot;
392086de 37366+ struct kstatfs *st;
1facf9fc 37367+ struct au_branch *br;
acd2b654 37368+ struct au_xino *xi;
1facf9fc 37369+
392086de 37370+ err = -ENOMEM;
be52b249 37371+ st = kmalloc(sizeof(*st), GFP_NOFS);
392086de
AM
37372+ if (unlikely(!st))
37373+ goto out;
37374+
1facf9fc 37375+ err = -EINVAL;
5afbbe0d
AM
37376+ bbot = au_sbbot(sb);
37377+ if (unlikely(bindex < 0 || bbot < bindex))
392086de 37378+ goto out_st;
392086de 37379+
1facf9fc 37380+ err = 0;
acd2b654
AM
37381+ jiffy = jiffies;
37382+ br = au_sbr(sb, bindex);
37383+ xi = br->br_xino;
37384+ for (i = idx_begin; !err && i < xi->xi_nfile; i++)
37385+ err = au_xino_do_trunc(sb, bindex, i, st);
37386+ if (!err)
37387+ au_sbi(sb)->si_xino_jiffy = jiffy;
392086de
AM
37388+
37389+out_st:
9f237c51 37390+ au_kfree_rcu(st);
4f0767ce 37391+out:
1facf9fc 37392+ return err;
37393+}
37394+
37395+struct xino_do_trunc_args {
37396+ struct super_block *sb;
37397+ struct au_branch *br;
acd2b654 37398+ int idx;
1facf9fc 37399+};
37400+
37401+static void xino_do_trunc(void *_args)
37402+{
37403+ struct xino_do_trunc_args *args = _args;
37404+ struct super_block *sb;
37405+ struct au_branch *br;
37406+ struct inode *dir;
acd2b654 37407+ int err, idx;
1facf9fc 37408+ aufs_bindex_t bindex;
37409+
37410+ err = 0;
37411+ sb = args->sb;
5527c038 37412+ dir = d_inode(sb->s_root);
1facf9fc 37413+ br = args->br;
acd2b654 37414+ idx = args->idx;
1facf9fc 37415+
37416+ si_noflush_write_lock(sb);
37417+ ii_read_lock_parent(dir);
37418+ bindex = au_br_index(sb, br->br_id);
acd2b654 37419+ err = au_xino_trunc(sb, bindex, idx);
1facf9fc 37420+ ii_read_unlock(dir);
37421+ if (unlikely(err))
392086de 37422+ pr_warn("err b%d, (%d)\n", bindex, err);
062440b3 37423+ atomic_dec(&br->br_xino->xi_truncating);
acd2b654 37424+ au_lcnt_dec(&br->br_count);
1facf9fc 37425+ si_write_unlock(sb);
027c5e7a 37426+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 37427+ au_kfree_rcu(args);
1facf9fc 37428+}
37429+
acd2b654
AM
37430+/*
37431+ * returns the index in the xi_file array whose corresponding file is necessary
37432+ * to truncate, or -1 which means no need to truncate.
37433+ */
392086de
AM
37434+static int xino_trunc_test(struct super_block *sb, struct au_branch *br)
37435+{
37436+ int err;
acd2b654 37437+ unsigned int u;
392086de
AM
37438+ struct kstatfs st;
37439+ struct au_sbinfo *sbinfo;
acd2b654 37440+ struct au_xino *xi;
062440b3 37441+ struct file *file;
392086de
AM
37442+
37443+ /* todo: si_xino_expire and the ratio should be customizable */
37444+ sbinfo = au_sbi(sb);
37445+ if (time_before(jiffies,
37446+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire))
acd2b654 37447+ return -1;
392086de
AM
37448+
37449+ /* truncation border */
acd2b654
AM
37450+ xi = br->br_xino;
37451+ for (u = 0; u < xi->xi_nfile; u++) {
37452+ file = au_xino_file(xi, u);
37453+ if (!file)
37454+ continue;
37455+
37456+ err = vfs_statfs(&file->f_path, &st);
37457+ if (unlikely(err)) {
37458+ AuErr1("statfs err %d, ignored\n", err);
37459+ return -1;
37460+ }
37461+ if (div64_u64(st.f_bfree * 100, st.f_blocks)
37462+ >= AUFS_XINO_DEF_TRUNC)
37463+ return u;
392086de 37464+ }
392086de 37465+
acd2b654 37466+ return -1;
392086de
AM
37467+}
37468+
1facf9fc 37469+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
37470+{
acd2b654 37471+ int idx;
1facf9fc 37472+ struct xino_do_trunc_args *args;
37473+ int wkq_err;
37474+
acd2b654
AM
37475+ idx = xino_trunc_test(sb, br);
37476+ if (idx < 0)
1facf9fc 37477+ return;
37478+
062440b3 37479+ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1)
1facf9fc 37480+ goto out;
37481+
37482+ /* lock and kfree() will be called in trunc_xino() */
37483+ args = kmalloc(sizeof(*args), GFP_NOFS);
37484+ if (unlikely(!args)) {
37485+ AuErr1("no memory\n");
f0c0a007 37486+ goto out;
1facf9fc 37487+ }
37488+
acd2b654 37489+ au_lcnt_inc(&br->br_count);
1facf9fc 37490+ args->sb = sb;
37491+ args->br = br;
acd2b654 37492+ args->idx = idx;
53392da6 37493+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 37494+ if (!wkq_err)
37495+ return; /* success */
37496+
4a4d8108 37497+ pr_err("wkq %d\n", wkq_err);
acd2b654 37498+ au_lcnt_dec(&br->br_count);
9f237c51 37499+ au_kfree_rcu(args);
1facf9fc 37500+
4f0767ce 37501+out:
062440b3 37502+ atomic_dec(&br->br_xino->xi_truncating);
1facf9fc 37503+}
37504+
37505+/* ---------------------------------------------------------------------- */
37506+
acd2b654
AM
37507+struct au_xi_calc {
37508+ int idx;
37509+ loff_t pos;
37510+};
37511+
37512+static void au_xi_calc(struct super_block *sb, ino_t h_ino,
37513+ struct au_xi_calc *calc)
37514+{
37515+ loff_t maxent;
37516+
37517+ maxent = au_xi_maxent(sb);
37518+ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos);
37519+ calc->pos *= sizeof(ino_t);
37520+}
37521+
37522+static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br,
37523+ struct au_xi_calc *calc)
37524+{
37525+ int err;
37526+ struct file *file;
37527+ struct au_xino *xi = br->br_xino;
37528+ struct au_xi_new xinew = {
37529+ .xi = xi
37530+ };
37531+
37532+ SiMustAnyLock(sb);
37533+
37534+ err = 0;
37535+ if (!xi)
37536+ goto out;
37537+
37538+ mutex_lock(&xi->xi_mtx);
37539+ file = au_xino_file(xi, calc->idx);
37540+ if (file)
37541+ goto out_mtx;
37542+
37543+ file = au_xino_file(xi, /*idx*/-1);
37544+ AuDebugOn(!file);
37545+ xinew.idx = calc->idx;
37546+ xinew.base = &file->f_path;
37547+ /* xinew.copy_src = NULL; */
37548+ file = au_xi_new(sb, &xinew);
37549+ if (IS_ERR(file))
37550+ err = PTR_ERR(file);
37551+
37552+out_mtx:
37553+ mutex_unlock(&xi->xi_mtx);
37554+out:
37555+ return err;
37556+}
37557+
37558+struct au_xino_do_new_async_args {
37559+ struct super_block *sb;
37560+ struct au_branch *br;
37561+ struct au_xi_calc calc;
37562+ ino_t ino;
37563+};
37564+
9f237c51
AM
37565+struct au_xi_writing {
37566+ struct hlist_bl_node node;
37567+ ino_t h_ino, ino;
37568+};
37569+
acd2b654
AM
37570+static int au_xino_do_write(vfs_writef_t write, struct file *file,
37571+ struct au_xi_calc *calc, ino_t ino);
37572+
37573+static void au_xino_call_do_new_async(void *args)
37574+{
37575+ struct au_xino_do_new_async_args *a = args;
37576+ struct au_branch *br;
37577+ struct super_block *sb;
37578+ struct au_sbinfo *sbi;
37579+ struct inode *root;
37580+ struct file *file;
9f237c51
AM
37581+ struct au_xi_writing *del, *p;
37582+ struct hlist_bl_head *hbl;
37583+ struct hlist_bl_node *pos;
acd2b654
AM
37584+ int err;
37585+
37586+ br = a->br;
37587+ sb = a->sb;
37588+ sbi = au_sbi(sb);
37589+ si_noflush_read_lock(sb);
37590+ root = d_inode(sb->s_root);
37591+ ii_read_lock_child(root);
37592+ err = au_xino_do_new_async(sb, br, &a->calc);
9f237c51
AM
37593+ if (unlikely(err)) {
37594+ AuIOErr("err %d\n", err);
37595+ goto out;
37596+ }
37597+
37598+ file = au_xino_file(br->br_xino, a->calc.idx);
37599+ AuDebugOn(!file);
37600+ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino);
37601+ if (unlikely(err)) {
acd2b654 37602+ AuIOErr("err %d\n", err);
9f237c51
AM
37603+ goto out;
37604+ }
37605+
37606+ del = NULL;
37607+ hbl = &br->br_xino->xi_writing;
37608+ hlist_bl_lock(hbl);
37609+ au_hbl_for_each(pos, hbl) {
37610+ p = container_of(pos, struct au_xi_writing, node);
37611+ if (p->ino == a->ino) {
37612+ del = p;
37613+ hlist_bl_del(&p->node);
37614+ break;
37615+ }
37616+ }
37617+ hlist_bl_unlock(hbl);
37618+ au_kfree_rcu(del);
37619+
37620+out:
acd2b654
AM
37621+ au_lcnt_dec(&br->br_count);
37622+ ii_read_unlock(root);
37623+ si_read_unlock(sb);
37624+ au_nwt_done(&sbi->si_nowait);
9f237c51 37625+ au_kfree_rcu(a);
acd2b654
AM
37626+}
37627+
37628+/*
37629+ * create a new xino file asynchronously
37630+ */
37631+static int au_xino_new_async(struct super_block *sb, struct au_branch *br,
37632+ struct au_xi_calc *calc, ino_t ino)
37633+{
37634+ int err;
37635+ struct au_xino_do_new_async_args *arg;
37636+
37637+ err = -ENOMEM;
37638+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
37639+ if (unlikely(!arg))
37640+ goto out;
37641+
37642+ arg->sb = sb;
37643+ arg->br = br;
37644+ arg->calc = *calc;
37645+ arg->ino = ino;
37646+ au_lcnt_inc(&br->br_count);
37647+ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST);
37648+ if (unlikely(err)) {
37649+ pr_err("wkq %d\n", err);
37650+ au_lcnt_dec(&br->br_count);
9f237c51 37651+ au_kfree_rcu(arg);
acd2b654
AM
37652+ }
37653+
37654+out:
37655+ return err;
37656+}
37657+
062440b3
AM
37658+/*
37659+ * read @ino from xinofile for the specified branch{@sb, @bindex}
37660+ * at the position of @h_ino.
37661+ */
37662+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37663+ ino_t *ino)
37664+{
37665+ int err;
37666+ ssize_t sz;
acd2b654 37667+ struct au_xi_calc calc;
062440b3 37668+ struct au_sbinfo *sbinfo;
acd2b654 37669+ struct file *file;
9f237c51
AM
37670+ struct au_xino *xi;
37671+ struct hlist_bl_head *hbl;
37672+ struct hlist_bl_node *pos;
37673+ struct au_xi_writing *p;
062440b3
AM
37674+
37675+ *ino = 0;
37676+ if (!au_opt_test(au_mntflags(sb), XINO))
37677+ return 0; /* no xino */
37678+
37679+ err = 0;
acd2b654 37680+ au_xi_calc(sb, h_ino, &calc);
9f237c51
AM
37681+ xi = au_sbr(sb, bindex)->br_xino;
37682+ file = au_xino_file(xi, calc.idx);
37683+ if (!file) {
37684+ hbl = &xi->xi_writing;
37685+ hlist_bl_lock(hbl);
37686+ au_hbl_for_each(pos, hbl) {
37687+ p = container_of(pos, struct au_xi_writing, node);
37688+ if (p->h_ino == h_ino) {
37689+ AuDbg("hi%llu, i%llu, found\n",
37690+ (u64)p->h_ino, (u64)p->ino);
37691+ *ino = p->ino;
37692+ break;
37693+ }
37694+ }
37695+ hlist_bl_unlock(hbl);
37696+ return 0;
37697+ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino))
37698+ return 0; /* no xino */
062440b3 37699+
acd2b654
AM
37700+ sbinfo = au_sbi(sb);
37701+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos);
062440b3
AM
37702+ if (sz == sizeof(*ino))
37703+ return 0; /* success */
37704+
37705+ err = sz;
37706+ if (unlikely(sz >= 0)) {
37707+ err = -EIO;
37708+ AuIOErr("xino read error (%zd)\n", sz);
37709+ }
062440b3
AM
37710+ return err;
37711+}
37712+
5527c038 37713+static int au_xino_do_write(vfs_writef_t write, struct file *file,
acd2b654 37714+ struct au_xi_calc *calc, ino_t ino)
1facf9fc 37715+{
1facf9fc 37716+ ssize_t sz;
37717+
acd2b654 37718+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos);
1facf9fc 37719+ if (sz == sizeof(ino))
37720+ return 0; /* success */
37721+
37722+ AuIOErr("write failed (%zd)\n", sz);
37723+ return -EIO;
37724+}
37725+
37726+/*
37727+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
37728+ * at the position of @h_ino.
37729+ * even if @ino is zero, it is written to the xinofile and means no entry.
37730+ * if the size of the xino file on a specific filesystem exceeds the watermark,
37731+ * try truncating it.
37732+ */
37733+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37734+ ino_t ino)
37735+{
37736+ int err;
37737+ unsigned int mnt_flags;
acd2b654
AM
37738+ struct au_xi_calc calc;
37739+ struct file *file;
1facf9fc 37740+ struct au_branch *br;
acd2b654 37741+ struct au_xino *xi;
9f237c51 37742+ struct au_xi_writing *p;
1facf9fc 37743+
dece6358 37744+ SiMustAnyLock(sb);
1facf9fc 37745+
37746+ mnt_flags = au_mntflags(sb);
37747+ if (!au_opt_test(mnt_flags, XINO))
37748+ return 0;
37749+
acd2b654 37750+ au_xi_calc(sb, h_ino, &calc);
1facf9fc 37751+ br = au_sbr(sb, bindex);
acd2b654
AM
37752+ xi = br->br_xino;
37753+ file = au_xino_file(xi, calc.idx);
37754+ if (!file) {
9f237c51
AM
37755+ /* store the inum pair into the list */
37756+ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL);
37757+ p->h_ino = h_ino;
37758+ p->ino = ino;
37759+ au_hbl_add(&p->node, &xi->xi_writing);
37760+
acd2b654
AM
37761+ /* create and write a new xino file asynchronously */
37762+ err = au_xino_new_async(sb, br, &calc, ino);
37763+ if (!err)
37764+ return 0; /* success */
37765+ goto out;
37766+ }
37767+
37768+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino);
1facf9fc 37769+ if (!err) {
acd2b654 37770+ br = au_sbr(sb, bindex);
1facf9fc 37771+ if (au_opt_test(mnt_flags, TRUNC_XINO)
86dc4139 37772+ && au_test_fs_trunc_xino(au_br_sb(br)))
1facf9fc 37773+ xino_try_trunc(sb, br);
37774+ return 0; /* success */
37775+ }
37776+
acd2b654 37777+out:
1facf9fc 37778+ AuIOErr("write failed (%d)\n", err);
37779+ return -EIO;
37780+}
37781+
062440b3
AM
37782+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf,
37783+ size_t size, loff_t *pos);
1facf9fc 37784+
062440b3
AM
37785+/* todo: unnecessary to support mmap_sem since kernel-space? */
37786+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size,
37787+ loff_t *pos)
37788+{
37789+ ssize_t err;
37790+ mm_segment_t oldfs;
37791+ union {
37792+ void *k;
37793+ char __user *u;
37794+ } buf;
37795+ int i;
37796+ const int prevent_endless = 10;
1facf9fc 37797+
062440b3
AM
37798+ i = 0;
37799+ buf.k = kbuf;
37800+ oldfs = get_fs();
37801+ set_fs(KERNEL_DS);
37802+ do {
37803+ err = func(file, buf.u, size, pos);
37804+ if (err == -EINTR
37805+ && !au_wkq_test()
37806+ && fatal_signal_pending(current)) {
37807+ set_fs(oldfs);
37808+ err = xino_fread_wkq(func, file, kbuf, size, pos);
37809+ BUG_ON(err == -EINTR);
37810+ oldfs = get_fs();
37811+ set_fs(KERNEL_DS);
37812+ }
37813+ } while (i++ < prevent_endless
37814+ && (err == -EAGAIN || err == -EINTR));
37815+ set_fs(oldfs);
37816+
37817+#if 0 /* reserved for future use */
37818+ if (err > 0)
37819+ fsnotify_access(file->f_path.dentry);
37820+#endif
37821+
37822+ return err;
37823+}
37824+
37825+struct xino_fread_args {
37826+ ssize_t *errp;
37827+ vfs_readf_t func;
37828+ struct file *file;
37829+ void *buf;
37830+ size_t size;
37831+ loff_t *pos;
37832+};
37833+
37834+static void call_xino_fread(void *args)
37835+{
37836+ struct xino_fread_args *a = args;
37837+ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos);
37838+}
37839+
37840+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf,
37841+ size_t size, loff_t *pos)
37842+{
37843+ ssize_t err;
37844+ int wkq_err;
37845+ struct xino_fread_args args = {
37846+ .errp = &err,
37847+ .func = func,
37848+ .file = file,
37849+ .buf = buf,
37850+ .size = size,
37851+ .pos = pos
37852+ };
37853+
37854+ wkq_err = au_wkq_wait(call_xino_fread, &args);
37855+ if (unlikely(wkq_err))
37856+ err = wkq_err;
37857+
37858+ return err;
37859+}
37860+
37861+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
37862+ size_t size, loff_t *pos);
37863+
37864+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf,
37865+ size_t size, loff_t *pos)
37866+{
37867+ ssize_t err;
37868+ mm_segment_t oldfs;
37869+ union {
37870+ void *k;
37871+ const char __user *u;
37872+ } buf;
37873+ int i;
37874+ const int prevent_endless = 10;
37875+
37876+ i = 0;
37877+ buf.k = kbuf;
37878+ oldfs = get_fs();
37879+ set_fs(KERNEL_DS);
37880+ do {
37881+ err = func(file, buf.u, size, pos);
37882+ if (err == -EINTR
37883+ && !au_wkq_test()
37884+ && fatal_signal_pending(current)) {
37885+ set_fs(oldfs);
37886+ err = xino_fwrite_wkq(func, file, kbuf, size, pos);
37887+ BUG_ON(err == -EINTR);
37888+ oldfs = get_fs();
37889+ set_fs(KERNEL_DS);
37890+ }
37891+ } while (i++ < prevent_endless
37892+ && (err == -EAGAIN || err == -EINTR));
37893+ set_fs(oldfs);
37894+
37895+#if 0 /* reserved for future use */
37896+ if (err > 0)
37897+ fsnotify_modify(file->f_path.dentry);
37898+#endif
37899+
37900+ return err;
37901+}
37902+
37903+struct do_xino_fwrite_args {
37904+ ssize_t *errp;
37905+ vfs_writef_t func;
37906+ struct file *file;
37907+ void *buf;
37908+ size_t size;
37909+ loff_t *pos;
37910+};
37911+
37912+static void call_do_xino_fwrite(void *args)
37913+{
37914+ struct do_xino_fwrite_args *a = args;
37915+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
37916+}
37917+
37918+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
37919+ size_t size, loff_t *pos)
37920+{
37921+ ssize_t err;
37922+ int wkq_err;
37923+ struct do_xino_fwrite_args args = {
37924+ .errp = &err,
37925+ .func = func,
37926+ .file = file,
37927+ .buf = buf,
37928+ .size = size,
37929+ .pos = pos
37930+ };
37931+
37932+ /*
37933+ * it breaks RLIMIT_FSIZE and normal user's limit,
37934+ * users should care about quota and real 'filesystem full.'
37935+ */
37936+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
37937+ if (unlikely(wkq_err))
37938+ err = wkq_err;
37939+
37940+ return err;
37941+}
37942+
37943+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
37944+ size_t size, loff_t *pos)
37945+{
37946+ ssize_t err;
37947+
37948+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
37949+ lockdep_off();
37950+ err = do_xino_fwrite(func, file, buf, size, pos);
37951+ lockdep_on();
37952+ } else {
37953+ lockdep_off();
37954+ err = xino_fwrite_wkq(func, file, buf, size, pos);
37955+ lockdep_on();
37956+ }
37957+
37958+ return err;
37959+}
37960+
37961+/* ---------------------------------------------------------------------- */
37962+
37963+/*
37964+ * inode number bitmap
37965+ */
1facf9fc 37966+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
37967+static ino_t xib_calc_ino(unsigned long pindex, int bit)
37968+{
37969+ ino_t ino;
37970+
37971+ AuDebugOn(bit < 0 || page_bits <= bit);
37972+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
37973+ return ino;
37974+}
37975+
37976+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
37977+{
37978+ AuDebugOn(ino < AUFS_FIRST_INO);
37979+ ino -= AUFS_FIRST_INO;
37980+ *pindex = ino / page_bits;
37981+ *bit = ino % page_bits;
37982+}
37983+
37984+static int xib_pindex(struct super_block *sb, unsigned long pindex)
37985+{
37986+ int err;
37987+ loff_t pos;
37988+ ssize_t sz;
37989+ struct au_sbinfo *sbinfo;
37990+ struct file *xib;
37991+ unsigned long *p;
37992+
37993+ sbinfo = au_sbi(sb);
37994+ MtxMustLock(&sbinfo->si_xib_mtx);
37995+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
37996+ || !au_opt_test(sbinfo->si_mntflags, XINO));
37997+
37998+ if (pindex == sbinfo->si_xib_last_pindex)
37999+ return 0;
38000+
38001+ xib = sbinfo->si_xib;
38002+ p = sbinfo->si_xib_buf;
38003+ pos = sbinfo->si_xib_last_pindex;
38004+ pos *= PAGE_SIZE;
38005+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
38006+ if (unlikely(sz != PAGE_SIZE))
38007+ goto out;
38008+
38009+ pos = pindex;
38010+ pos *= PAGE_SIZE;
c06a8ce3 38011+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE)
1facf9fc 38012+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
38013+ else {
38014+ memset(p, 0, PAGE_SIZE);
38015+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
38016+ }
38017+ if (sz == PAGE_SIZE) {
38018+ sbinfo->si_xib_last_pindex = pindex;
38019+ return 0; /* success */
38020+ }
38021+
4f0767ce 38022+out:
b752ccd1
AM
38023+ AuIOErr1("write failed (%zd)\n", sz);
38024+ err = sz;
38025+ if (sz >= 0)
38026+ err = -EIO;
38027+ return err;
38028+}
38029+
b752ccd1
AM
38030+static void au_xib_clear_bit(struct inode *inode)
38031+{
38032+ int err, bit;
38033+ unsigned long pindex;
38034+ struct super_block *sb;
38035+ struct au_sbinfo *sbinfo;
38036+
38037+ AuDebugOn(inode->i_nlink);
38038+
38039+ sb = inode->i_sb;
38040+ xib_calc_bit(inode->i_ino, &pindex, &bit);
38041+ AuDebugOn(page_bits <= bit);
38042+ sbinfo = au_sbi(sb);
38043+ mutex_lock(&sbinfo->si_xib_mtx);
38044+ err = xib_pindex(sb, pindex);
38045+ if (!err) {
38046+ clear_bit(bit, sbinfo->si_xib_buf);
38047+ sbinfo->si_xib_next_bit = bit;
38048+ }
38049+ mutex_unlock(&sbinfo->si_xib_mtx);
38050+}
38051+
1facf9fc 38052+/* ---------------------------------------------------------------------- */
38053+
1facf9fc 38054+/*
062440b3 38055+ * truncate a xino bitmap file
1facf9fc 38056+ */
1facf9fc 38057+
38058+/* todo: slow */
38059+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
38060+{
38061+ int err, bit;
38062+ ssize_t sz;
38063+ unsigned long pindex;
38064+ loff_t pos, pend;
38065+ struct au_sbinfo *sbinfo;
5527c038 38066+ vfs_readf_t func;
1facf9fc 38067+ ino_t *ino;
38068+ unsigned long *p;
38069+
38070+ err = 0;
38071+ sbinfo = au_sbi(sb);
dece6358 38072+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 38073+ p = sbinfo->si_xib_buf;
38074+ func = sbinfo->si_xread;
c06a8ce3 38075+ pend = vfsub_f_size_read(file);
1facf9fc 38076+ pos = 0;
38077+ while (pos < pend) {
38078+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
38079+ err = sz;
38080+ if (unlikely(sz <= 0))
38081+ goto out;
38082+
38083+ err = 0;
38084+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
38085+ if (unlikely(*ino < AUFS_FIRST_INO))
38086+ continue;
38087+
38088+ xib_calc_bit(*ino, &pindex, &bit);
38089+ AuDebugOn(page_bits <= bit);
38090+ err = xib_pindex(sb, pindex);
38091+ if (!err)
38092+ set_bit(bit, p);
38093+ else
38094+ goto out;
38095+ }
38096+ }
38097+
4f0767ce 38098+out:
1facf9fc 38099+ return err;
38100+}
38101+
38102+static int xib_restore(struct super_block *sb)
38103+{
acd2b654
AM
38104+ int err, i;
38105+ unsigned int nfile;
5afbbe0d 38106+ aufs_bindex_t bindex, bbot;
1facf9fc 38107+ void *page;
062440b3 38108+ struct au_branch *br;
acd2b654
AM
38109+ struct au_xino *xi;
38110+ struct file *file;
1facf9fc 38111+
38112+ err = -ENOMEM;
38113+ page = (void *)__get_free_page(GFP_NOFS);
38114+ if (unlikely(!page))
38115+ goto out;
38116+
38117+ err = 0;
5afbbe0d
AM
38118+ bbot = au_sbbot(sb);
38119+ for (bindex = 0; !err && bindex <= bbot; bindex++)
062440b3
AM
38120+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) {
38121+ br = au_sbr(sb, bindex);
acd2b654
AM
38122+ xi = br->br_xino;
38123+ nfile = xi->xi_nfile;
38124+ for (i = 0; i < nfile; i++) {
38125+ file = au_xino_file(xi, i);
38126+ if (file)
38127+ err = do_xib_restore(sb, file, page);
38128+ }
062440b3
AM
38129+ } else
38130+ AuDbg("skip shared b%d\n", bindex);
1c60b727 38131+ free_page((unsigned long)page);
1facf9fc 38132+
4f0767ce 38133+out:
1facf9fc 38134+ return err;
38135+}
38136+
38137+int au_xib_trunc(struct super_block *sb)
38138+{
38139+ int err;
38140+ ssize_t sz;
38141+ loff_t pos;
1facf9fc 38142+ struct au_sbinfo *sbinfo;
38143+ unsigned long *p;
38144+ struct file *file;
38145+
dece6358
AM
38146+ SiMustWriteLock(sb);
38147+
1facf9fc 38148+ err = 0;
38149+ sbinfo = au_sbi(sb);
38150+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
38151+ goto out;
38152+
38153+ file = sbinfo->si_xib;
c06a8ce3 38154+ if (vfsub_f_size_read(file) <= PAGE_SIZE)
1facf9fc 38155+ goto out;
38156+
062440b3 38157+ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL);
1facf9fc 38158+ err = PTR_ERR(file);
38159+ if (IS_ERR(file))
38160+ goto out;
38161+ fput(sbinfo->si_xib);
38162+ sbinfo->si_xib = file;
38163+
38164+ p = sbinfo->si_xib_buf;
38165+ memset(p, 0, PAGE_SIZE);
38166+ pos = 0;
38167+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
38168+ if (unlikely(sz != PAGE_SIZE)) {
38169+ err = sz;
38170+ AuIOErr("err %d\n", err);
38171+ if (sz >= 0)
38172+ err = -EIO;
38173+ goto out;
38174+ }
38175+
38176+ mutex_lock(&sbinfo->si_xib_mtx);
38177+ /* mnt_want_write() is unnecessary here */
38178+ err = xib_restore(sb);
38179+ mutex_unlock(&sbinfo->si_xib_mtx);
38180+
38181+out:
38182+ return err;
38183+}
38184+
38185+/* ---------------------------------------------------------------------- */
38186+
acd2b654 38187+struct au_xino *au_xino_alloc(unsigned int nfile)
062440b3
AM
38188+{
38189+ struct au_xino *xi;
38190+
38191+ xi = kzalloc(sizeof(*xi), GFP_NOFS);
38192+ if (unlikely(!xi))
38193+ goto out;
acd2b654
AM
38194+ xi->xi_nfile = nfile;
38195+ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS);
38196+ if (unlikely(!xi->xi_file))
38197+ goto out_free;
062440b3
AM
38198+
38199+ xi->xi_nondir.total = 8; /* initial size */
38200+ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t),
38201+ GFP_NOFS);
38202+ if (unlikely(!xi->xi_nondir.array))
acd2b654 38203+ goto out_file;
062440b3
AM
38204+
38205+ spin_lock_init(&xi->xi_nondir.spin);
38206+ init_waitqueue_head(&xi->xi_nondir.wqh);
acd2b654 38207+ mutex_init(&xi->xi_mtx);
9f237c51 38208+ INIT_HLIST_BL_HEAD(&xi->xi_writing);
062440b3
AM
38209+ atomic_set(&xi->xi_truncating, 0);
38210+ kref_init(&xi->xi_kref);
38211+ goto out; /* success */
38212+
acd2b654 38213+out_file:
9f237c51 38214+ au_kfree_try_rcu(xi->xi_file);
062440b3 38215+out_free:
9f237c51 38216+ au_kfree_rcu(xi);
062440b3
AM
38217+ xi = NULL;
38218+out:
38219+ return xi;
38220+}
38221+
acd2b654 38222+static int au_xino_init(struct au_branch *br, int idx, struct file *file)
062440b3
AM
38223+{
38224+ int err;
38225+ struct au_xino *xi;
38226+
38227+ err = 0;
acd2b654 38228+ xi = au_xino_alloc(idx + 1);
062440b3
AM
38229+ if (unlikely(!xi)) {
38230+ err = -ENOMEM;
38231+ goto out;
38232+ }
38233+
acd2b654
AM
38234+ if (file)
38235+ get_file(file);
38236+ xi->xi_file[idx] = file;
062440b3
AM
38237+ AuDebugOn(br->br_xino);
38238+ br->br_xino = xi;
38239+
38240+out:
38241+ return err;
38242+}
38243+
38244+static void au_xino_release(struct kref *kref)
38245+{
38246+ struct au_xino *xi;
38247+ int i;
9f237c51
AM
38248+ unsigned long ul;
38249+ struct hlist_bl_head *hbl;
38250+ struct hlist_bl_node *pos, *n;
38251+ struct au_xi_writing *p;
062440b3
AM
38252+
38253+ xi = container_of(kref, struct au_xino, xi_kref);
acd2b654
AM
38254+ for (i = 0; i < xi->xi_nfile; i++)
38255+ if (xi->xi_file[i])
38256+ fput(xi->xi_file[i]);
062440b3
AM
38257+ for (i = xi->xi_nondir.total - 1; i >= 0; i--)
38258+ AuDebugOn(xi->xi_nondir.array[i]);
acd2b654 38259+ mutex_destroy(&xi->xi_mtx);
9f237c51
AM
38260+ hbl = &xi->xi_writing;
38261+ ul = au_hbl_count(hbl);
38262+ if (unlikely(ul)) {
38263+ pr_warn("xi_writing %lu\n", ul);
38264+ hlist_bl_lock(hbl);
38265+ hlist_bl_for_each_entry_safe (p, pos, n, hbl, node) {
38266+ hlist_bl_del(&p->node);
38267+ au_kfree_rcu(p);
38268+ }
38269+ hlist_bl_unlock(hbl);
38270+ }
38271+ au_kfree_try_rcu(xi->xi_file);
38272+ au_kfree_try_rcu(xi->xi_nondir.array);
38273+ au_kfree_rcu(xi);
062440b3
AM
38274+}
38275+
38276+int au_xino_put(struct au_branch *br)
38277+{
38278+ int ret;
38279+ struct au_xino *xi;
38280+
38281+ ret = 0;
38282+ xi = br->br_xino;
38283+ if (xi) {
38284+ br->br_xino = NULL;
38285+ ret = kref_put(&xi->xi_kref, au_xino_release);
38286+ }
38287+
38288+ return ret;
38289+}
38290+
062440b3
AM
38291+/* ---------------------------------------------------------------------- */
38292+
1facf9fc 38293+/*
38294+ * xino mount option handlers
38295+ */
1facf9fc 38296+
38297+/* xino bitmap */
38298+static void xino_clear_xib(struct super_block *sb)
38299+{
38300+ struct au_sbinfo *sbinfo;
38301+
dece6358
AM
38302+ SiMustWriteLock(sb);
38303+
1facf9fc 38304+ sbinfo = au_sbi(sb);
062440b3 38305+ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */
1facf9fc 38306+ if (sbinfo->si_xib)
38307+ fput(sbinfo->si_xib);
38308+ sbinfo->si_xib = NULL;
f0c0a007 38309+ if (sbinfo->si_xib_buf)
1c60b727 38310+ free_page((unsigned long)sbinfo->si_xib_buf);
1facf9fc 38311+ sbinfo->si_xib_buf = NULL;
38312+}
38313+
062440b3 38314+static int au_xino_set_xib(struct super_block *sb, struct path *path)
1facf9fc 38315+{
38316+ int err;
38317+ loff_t pos;
38318+ struct au_sbinfo *sbinfo;
38319+ struct file *file;
acd2b654 38320+ struct super_block *xi_sb;
1facf9fc 38321+
dece6358
AM
38322+ SiMustWriteLock(sb);
38323+
1facf9fc 38324+ sbinfo = au_sbi(sb);
062440b3 38325+ file = au_xino_create2(sb, path, sbinfo->si_xib);
1facf9fc 38326+ err = PTR_ERR(file);
38327+ if (IS_ERR(file))
38328+ goto out;
38329+ if (sbinfo->si_xib)
38330+ fput(sbinfo->si_xib);
38331+ sbinfo->si_xib = file;
5527c038
JR
38332+ sbinfo->si_xread = vfs_readf(file);
38333+ sbinfo->si_xwrite = vfs_writef(file);
acd2b654
AM
38334+ xi_sb = file_inode(file)->i_sb;
38335+ sbinfo->si_ximaxent = xi_sb->s_maxbytes;
38336+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) {
38337+ err = -EIO;
38338+ pr_err("s_maxbytes(%llu) on %s is too small\n",
38339+ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb));
38340+ goto out_unset;
38341+ }
38342+ sbinfo->si_ximaxent /= sizeof(ino_t);
1facf9fc 38343+
38344+ err = -ENOMEM;
38345+ if (!sbinfo->si_xib_buf)
38346+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
38347+ if (unlikely(!sbinfo->si_xib_buf))
38348+ goto out_unset;
38349+
38350+ sbinfo->si_xib_last_pindex = 0;
38351+ sbinfo->si_xib_next_bit = 0;
c06a8ce3 38352+ if (vfsub_f_size_read(file) < PAGE_SIZE) {
1facf9fc 38353+ pos = 0;
38354+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
38355+ PAGE_SIZE, &pos);
38356+ if (unlikely(err != PAGE_SIZE))
38357+ goto out_free;
38358+ }
38359+ err = 0;
38360+ goto out; /* success */
38361+
4f0767ce 38362+out_free:
f0c0a007 38363+ if (sbinfo->si_xib_buf)
1c60b727 38364+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
38365+ sbinfo->si_xib_buf = NULL;
38366+ if (err >= 0)
38367+ err = -EIO;
4f0767ce 38368+out_unset:
b752ccd1
AM
38369+ fput(sbinfo->si_xib);
38370+ sbinfo->si_xib = NULL;
4f0767ce 38371+out:
062440b3 38372+ AuTraceErr(err);
b752ccd1 38373+ return err;
1facf9fc 38374+}
38375+
b752ccd1
AM
38376+/* xino for each branch */
38377+static void xino_clear_br(struct super_block *sb)
38378+{
5afbbe0d 38379+ aufs_bindex_t bindex, bbot;
b752ccd1 38380+ struct au_branch *br;
1facf9fc 38381+
5afbbe0d
AM
38382+ bbot = au_sbbot(sb);
38383+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1 38384+ br = au_sbr(sb, bindex);
062440b3
AM
38385+ AuDebugOn(!br);
38386+ au_xino_put(br);
38387+ }
38388+}
38389+
38390+static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br,
38391+ aufs_bindex_t bshared)
38392+{
38393+ struct au_branch *brshared;
b752ccd1 38394+
062440b3
AM
38395+ brshared = au_sbr(sb, bshared);
38396+ AuDebugOn(!brshared->br_xino);
38397+ AuDebugOn(!brshared->br_xino->xi_file);
38398+ if (br->br_xino != brshared->br_xino) {
38399+ au_xino_get(brshared);
38400+ au_xino_put(br);
38401+ br->br_xino = brshared->br_xino;
b752ccd1
AM
38402+ }
38403+}
38404+
062440b3
AM
38405+struct au_xino_do_set_br {
38406+ vfs_writef_t writef;
38407+ struct au_branch *br;
38408+ ino_t h_ino;
38409+ aufs_bindex_t bshared;
38410+};
38411+
38412+static int au_xino_do_set_br(struct super_block *sb, struct path *path,
38413+ struct au_xino_do_set_br *args)
1facf9fc 38414+{
38415+ int err;
acd2b654 38416+ struct au_xi_calc calc;
062440b3 38417+ struct file *file;
acd2b654
AM
38418+ struct au_branch *br;
38419+ struct au_xi_new xinew = {
38420+ .base = path
38421+ };
062440b3 38422+
acd2b654
AM
38423+ br = args->br;
38424+ xinew.xi = br->br_xino;
38425+ au_xi_calc(sb, args->h_ino, &calc);
38426+ xinew.copy_src = au_xino_file(xinew.xi, calc.idx);
38427+ if (args->bshared >= 0)
062440b3 38428+ /* shared xino */
acd2b654
AM
38429+ au_xino_set_br_shared(sb, br, args->bshared);
38430+ else if (!xinew.xi) {
38431+ /* new xino */
38432+ err = au_xino_init(br, calc.idx, xinew.copy_src);
38433+ if (unlikely(err))
38434+ goto out;
062440b3
AM
38435+ }
38436+
acd2b654
AM
38437+ /* force re-creating */
38438+ xinew.xi = br->br_xino;
38439+ xinew.idx = calc.idx;
38440+ mutex_lock(&xinew.xi->xi_mtx);
38441+ file = au_xi_new(sb, &xinew);
38442+ mutex_unlock(&xinew.xi->xi_mtx);
062440b3
AM
38443+ err = PTR_ERR(file);
38444+ if (IS_ERR(file))
38445+ goto out;
acd2b654
AM
38446+ AuDebugOn(!file);
38447+
38448+ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO);
38449+ if (unlikely(err))
38450+ au_xino_put(br);
062440b3 38451+
062440b3
AM
38452+out:
38453+ AuTraceErr(err);
38454+ return err;
38455+}
38456+
38457+static int au_xino_set_br(struct super_block *sb, struct path *path)
38458+{
38459+ int err;
38460+ aufs_bindex_t bindex, bbot;
38461+ struct au_xino_do_set_br args;
b752ccd1 38462+ struct inode *inode;
1facf9fc 38463+
b752ccd1
AM
38464+ SiMustWriteLock(sb);
38465+
5afbbe0d 38466+ bbot = au_sbbot(sb);
5527c038 38467+ inode = d_inode(sb->s_root);
062440b3
AM
38468+ args.writef = au_sbi(sb)->si_xwrite;
38469+ for (bindex = 0; bindex <= bbot; bindex++) {
38470+ args.h_ino = au_h_iptr(inode, bindex)->i_ino;
38471+ args.br = au_sbr(sb, bindex);
38472+ args.bshared = is_sb_shared(sb, bindex, bindex - 1);
38473+ err = au_xino_do_set_br(sb, path, &args);
b752ccd1 38474+ if (unlikely(err))
062440b3 38475+ break;
b752ccd1 38476+ }
1facf9fc 38477+
062440b3 38478+ AuTraceErr(err);
1facf9fc 38479+ return err;
38480+}
b752ccd1
AM
38481+
38482+void au_xino_clr(struct super_block *sb)
38483+{
38484+ struct au_sbinfo *sbinfo;
38485+
38486+ au_xigen_clr(sb);
38487+ xino_clear_xib(sb);
38488+ xino_clear_br(sb);
062440b3 38489+ dbgaufs_brs_del(sb, 0);
b752ccd1
AM
38490+ sbinfo = au_sbi(sb);
38491+ /* lvalue, do not call au_mntflags() */
38492+ au_opt_clr(sbinfo->si_mntflags, XINO);
38493+}
38494+
062440b3 38495+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount)
b752ccd1
AM
38496+{
38497+ int err, skip;
062440b3 38498+ struct dentry *dentry, *parent, *cur_dentry, *cur_parent;
b752ccd1
AM
38499+ struct qstr *dname, *cur_name;
38500+ struct file *cur_xino;
b752ccd1 38501+ struct au_sbinfo *sbinfo;
062440b3 38502+ struct path *path, *cur_path;
b752ccd1
AM
38503+
38504+ SiMustWriteLock(sb);
38505+
38506+ err = 0;
38507+ sbinfo = au_sbi(sb);
062440b3
AM
38508+ path = &xiopt->file->f_path;
38509+ dentry = path->dentry;
38510+ parent = dget_parent(dentry);
b752ccd1
AM
38511+ if (remount) {
38512+ skip = 0;
b752ccd1
AM
38513+ cur_xino = sbinfo->si_xib;
38514+ if (cur_xino) {
062440b3
AM
38515+ cur_path = &cur_xino->f_path;
38516+ cur_dentry = cur_path->dentry;
38517+ cur_parent = dget_parent(cur_dentry);
38518+ cur_name = &cur_dentry->d_name;
38519+ dname = &dentry->d_name;
b752ccd1 38520+ skip = (cur_parent == parent
38d290e6 38521+ && au_qstreq(dname, cur_name));
b752ccd1
AM
38522+ dput(cur_parent);
38523+ }
38524+ if (skip)
38525+ goto out;
38526+ }
38527+
38528+ au_opt_set(sbinfo->si_mntflags, XINO);
062440b3
AM
38529+ err = au_xino_set_xib(sb, path);
38530+ /* si_x{read,write} are set */
b752ccd1 38531+ if (!err)
062440b3 38532+ err = au_xigen_set(sb, path);
b752ccd1 38533+ if (!err)
062440b3
AM
38534+ err = au_xino_set_br(sb, path);
38535+ if (!err) {
38536+ dbgaufs_brs_add(sb, 0, /*topdown*/1);
b752ccd1 38537+ goto out; /* success */
062440b3 38538+ }
b752ccd1
AM
38539+
38540+ /* reset all */
062440b3
AM
38541+ AuIOErr("failed setting xino(%d).\n", err);
38542+ au_xino_clr(sb);
b752ccd1 38543+
4f0767ce 38544+out:
b752ccd1
AM
38545+ dput(parent);
38546+ return err;
38547+}
38548+
b752ccd1
AM
38549+/*
38550+ * create a xinofile at the default place/path.
38551+ */
38552+struct file *au_xino_def(struct super_block *sb)
38553+{
38554+ struct file *file;
38555+ char *page, *p;
38556+ struct au_branch *br;
38557+ struct super_block *h_sb;
38558+ struct path path;
5afbbe0d 38559+ aufs_bindex_t bbot, bindex, bwr;
b752ccd1
AM
38560+
38561+ br = NULL;
5afbbe0d 38562+ bbot = au_sbbot(sb);
b752ccd1 38563+ bwr = -1;
5afbbe0d 38564+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1
AM
38565+ br = au_sbr(sb, bindex);
38566+ if (au_br_writable(br->br_perm)
86dc4139 38567+ && !au_test_fs_bad_xino(au_br_sb(br))) {
b752ccd1
AM
38568+ bwr = bindex;
38569+ break;
38570+ }
38571+ }
38572+
7f207e10
AM
38573+ if (bwr >= 0) {
38574+ file = ERR_PTR(-ENOMEM);
537831f9 38575+ page = (void *)__get_free_page(GFP_NOFS);
7f207e10
AM
38576+ if (unlikely(!page))
38577+ goto out;
86dc4139 38578+ path.mnt = au_br_mnt(br);
7f207e10
AM
38579+ path.dentry = au_h_dptr(sb->s_root, bwr);
38580+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
38581+ file = (void *)p;
38582+ if (!IS_ERR(p)) {
38583+ strcat(p, "/" AUFS_XINO_FNAME);
38584+ AuDbg("%s\n", p);
83b672a5 38585+ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1);
7f207e10 38586+ }
1c60b727 38587+ free_page((unsigned long)page);
7f207e10 38588+ } else {
83b672a5
AM
38589+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
38590+ /*wbrtop*/0);
7f207e10
AM
38591+ if (IS_ERR(file))
38592+ goto out;
2000de60 38593+ h_sb = file->f_path.dentry->d_sb;
7f207e10
AM
38594+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
38595+ pr_err("xino doesn't support %s(%s)\n",
38596+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
38597+ fput(file);
38598+ file = ERR_PTR(-EINVAL);
38599+ }
7f207e10 38600+ }
0c5527e5 38601+
7f207e10
AM
38602+out:
38603+ return file;
38604+}
38605+
38606+/* ---------------------------------------------------------------------- */
38607+
062440b3
AM
38608+/*
38609+ * initialize the xinofile for the specified branch @br
38610+ * at the place/path where @base_file indicates.
38611+ * test whether another branch is on the same filesystem or not,
38612+ * if found then share the xinofile with another branch.
38613+ */
38614+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
38615+ struct path *base)
7f207e10
AM
38616+{
38617+ int err;
062440b3
AM
38618+ struct au_xino_do_set_br args = {
38619+ .h_ino = h_ino,
38620+ .br = br
38621+ };
7f207e10 38622+
062440b3
AM
38623+ args.writef = au_sbi(sb)->si_xwrite;
38624+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb),
38625+ au_br_sb(br));
38626+ err = au_xino_do_set_br(sb, base, &args);
79b8bda9 38627+ if (unlikely(err))
062440b3 38628+ au_xino_put(br);
7f207e10 38629+
7f207e10
AM
38630+ return err;
38631+}
521ced18
JR
38632+
38633+/* ---------------------------------------------------------------------- */
38634+
062440b3
AM
38635+/*
38636+ * get an unused inode number from bitmap
38637+ */
38638+ino_t au_xino_new_ino(struct super_block *sb)
38639+{
38640+ ino_t ino;
38641+ unsigned long *p, pindex, ul, pend;
38642+ struct au_sbinfo *sbinfo;
38643+ struct file *file;
38644+ int free_bit, err;
38645+
38646+ if (!au_opt_test(au_mntflags(sb), XINO))
38647+ return iunique(sb, AUFS_FIRST_INO);
38648+
38649+ sbinfo = au_sbi(sb);
38650+ mutex_lock(&sbinfo->si_xib_mtx);
38651+ p = sbinfo->si_xib_buf;
38652+ free_bit = sbinfo->si_xib_next_bit;
38653+ if (free_bit < page_bits && !test_bit(free_bit, p))
38654+ goto out; /* success */
38655+ free_bit = find_first_zero_bit(p, page_bits);
38656+ if (free_bit < page_bits)
38657+ goto out; /* success */
38658+
38659+ pindex = sbinfo->si_xib_last_pindex;
38660+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
38661+ err = xib_pindex(sb, ul);
38662+ if (unlikely(err))
38663+ goto out_err;
38664+ free_bit = find_first_zero_bit(p, page_bits);
38665+ if (free_bit < page_bits)
38666+ goto out; /* success */
38667+ }
38668+
38669+ file = sbinfo->si_xib;
38670+ pend = vfsub_f_size_read(file) / PAGE_SIZE;
38671+ for (ul = pindex + 1; ul <= pend; ul++) {
38672+ err = xib_pindex(sb, ul);
38673+ if (unlikely(err))
38674+ goto out_err;
38675+ free_bit = find_first_zero_bit(p, page_bits);
38676+ if (free_bit < page_bits)
38677+ goto out; /* success */
38678+ }
38679+ BUG();
38680+
38681+out:
38682+ set_bit(free_bit, p);
38683+ sbinfo->si_xib_next_bit = free_bit + 1;
38684+ pindex = sbinfo->si_xib_last_pindex;
38685+ mutex_unlock(&sbinfo->si_xib_mtx);
38686+ ino = xib_calc_ino(pindex, free_bit);
38687+ AuDbg("i%lu\n", (unsigned long)ino);
38688+ return ino;
38689+out_err:
38690+ mutex_unlock(&sbinfo->si_xib_mtx);
38691+ AuDbg("i0\n");
38692+ return 0;
38693+}
38694+
38695+/* for s_op->delete_inode() */
38696+void au_xino_delete_inode(struct inode *inode, const int unlinked)
521ced18 38697+{
062440b3
AM
38698+ int err;
38699+ unsigned int mnt_flags;
38700+ aufs_bindex_t bindex, bbot, bi;
38701+ unsigned char try_trunc;
38702+ struct au_iinfo *iinfo;
38703+ struct super_block *sb;
38704+ struct au_hinode *hi;
38705+ struct inode *h_inode;
38706+ struct au_branch *br;
38707+ vfs_writef_t xwrite;
acd2b654
AM
38708+ struct au_xi_calc calc;
38709+ struct file *file;
521ced18 38710+
062440b3 38711+ AuDebugOn(au_is_bad_inode(inode));
521ced18 38712+
062440b3
AM
38713+ sb = inode->i_sb;
38714+ mnt_flags = au_mntflags(sb);
38715+ if (!au_opt_test(mnt_flags, XINO)
38716+ || inode->i_ino == AUFS_ROOT_INO)
38717+ return;
38718+
38719+ if (unlinked) {
38720+ au_xigen_inc(inode);
38721+ au_xib_clear_bit(inode);
38722+ }
38723+
38724+ iinfo = au_ii(inode);
38725+ bindex = iinfo->ii_btop;
38726+ if (bindex < 0)
38727+ return;
38728+
38729+ xwrite = au_sbi(sb)->si_xwrite;
38730+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
38731+ hi = au_hinode(iinfo, bindex);
38732+ bbot = iinfo->ii_bbot;
38733+ for (; bindex <= bbot; bindex++, hi++) {
38734+ h_inode = hi->hi_inode;
38735+ if (!h_inode
38736+ || (!unlinked && h_inode->i_nlink))
38737+ continue;
38738+
38739+ /* inode may not be revalidated */
38740+ bi = au_br_index(sb, hi->hi_id);
38741+ if (bi < 0)
38742+ continue;
38743+
38744+ br = au_sbr(sb, bi);
acd2b654
AM
38745+ au_xi_calc(sb, h_inode->i_ino, &calc);
38746+ file = au_xino_file(br->br_xino, calc.idx);
38747+ if (IS_ERR_OR_NULL(file))
38748+ continue;
38749+
38750+ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0);
062440b3
AM
38751+ if (!err && try_trunc
38752+ && au_test_fs_trunc_xino(au_br_sb(br)))
38753+ xino_try_trunc(sb, br);
38754+ }
521ced18
JR
38755+}
38756+
062440b3
AM
38757+/* ---------------------------------------------------------------------- */
38758+
38759+static int au_xinondir_find(struct au_xino *xi, ino_t h_ino)
521ced18
JR
38760+{
38761+ int found, total, i;
38762+
38763+ found = -1;
062440b3 38764+ total = xi->xi_nondir.total;
521ced18 38765+ for (i = 0; i < total; i++) {
062440b3 38766+ if (xi->xi_nondir.array[i] != h_ino)
521ced18
JR
38767+ continue;
38768+ found = i;
38769+ break;
38770+ }
38771+
38772+ return found;
38773+}
38774+
062440b3 38775+static int au_xinondir_expand(struct au_xino *xi)
521ced18
JR
38776+{
38777+ int err, sz;
38778+ ino_t *p;
38779+
38780+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX);
38781+
38782+ err = -ENOMEM;
062440b3 38783+ sz = xi->xi_nondir.total * sizeof(ino_t);
521ced18
JR
38784+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2))
38785+ goto out;
062440b3 38786+ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC,
521ced18
JR
38787+ /*may_shrink*/0);
38788+ if (p) {
062440b3
AM
38789+ xi->xi_nondir.array = p;
38790+ xi->xi_nondir.total <<= 1;
38791+ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total);
521ced18
JR
38792+ err = 0;
38793+ }
38794+
38795+out:
38796+ return err;
38797+}
38798+
062440b3
AM
38799+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
38800+ ino_t h_ino, int idx)
38801+{
38802+ struct au_xino *xi;
38803+
38804+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
38805+ xi = au_sbr(sb, bindex)->br_xino;
38806+ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx);
38807+
38808+ spin_lock(&xi->xi_nondir.spin);
38809+ AuDebugOn(xi->xi_nondir.array[idx] != h_ino);
38810+ xi->xi_nondir.array[idx] = 0;
38811+ spin_unlock(&xi->xi_nondir.spin);
38812+ wake_up_all(&xi->xi_nondir.wqh);
38813+}
38814+
521ced18
JR
38815+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
38816+ int *idx)
38817+{
38818+ int err, found, empty;
062440b3 38819+ struct au_xino *xi;
521ced18
JR
38820+
38821+ err = 0;
38822+ *idx = -1;
38823+ if (!au_opt_test(au_mntflags(sb), XINO))
38824+ goto out; /* no xino */
38825+
062440b3 38826+ xi = au_sbr(sb, bindex)->br_xino;
521ced18
JR
38827+
38828+again:
062440b3
AM
38829+ spin_lock(&xi->xi_nondir.spin);
38830+ found = au_xinondir_find(xi, h_ino);
521ced18 38831+ if (found == -1) {
062440b3 38832+ empty = au_xinondir_find(xi, /*h_ino*/0);
521ced18 38833+ if (empty == -1) {
062440b3
AM
38834+ empty = xi->xi_nondir.total;
38835+ err = au_xinondir_expand(xi);
521ced18
JR
38836+ if (unlikely(err))
38837+ goto out_unlock;
38838+ }
062440b3 38839+ xi->xi_nondir.array[empty] = h_ino;
521ced18
JR
38840+ *idx = empty;
38841+ } else {
062440b3
AM
38842+ spin_unlock(&xi->xi_nondir.spin);
38843+ wait_event(xi->xi_nondir.wqh,
38844+ xi->xi_nondir.array[found] != h_ino);
521ced18
JR
38845+ goto again;
38846+ }
38847+
38848+out_unlock:
062440b3
AM
38849+ spin_unlock(&xi->xi_nondir.spin);
38850+out:
38851+ return err;
38852+}
38853+
38854+/* ---------------------------------------------------------------------- */
38855+
38856+int au_xino_path(struct seq_file *seq, struct file *file)
38857+{
38858+ int err;
38859+
38860+ err = au_seq_path(seq, &file->f_path);
38861+ if (unlikely(err))
38862+ goto out;
38863+
38864+#define Deleted "\\040(deleted)"
38865+ seq->count -= sizeof(Deleted) - 1;
38866+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
38867+ sizeof(Deleted) - 1));
38868+#undef Deleted
38869+
521ced18
JR
38870+out:
38871+ return err;
38872+}
537831f9 38873diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h
eca34b5c
AM
38874--- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
38875+++ linux/include/uapi/linux/aufs_type.h 2019-09-16 09:38:43.216175640 +0200
38876@@ -0,0 +1,452 @@
38877+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
7f207e10 38878+/*
ba1aed25 38879+ * Copyright (C) 2005-2019 Junjiro R. Okajima
7f207e10
AM
38880+ *
38881+ * This program, aufs is free software; you can redistribute it and/or modify
38882+ * it under the terms of the GNU General Public License as published by
38883+ * the Free Software Foundation; either version 2 of the License, or
38884+ * (at your option) any later version.
38885+ *
38886+ * This program is distributed in the hope that it will be useful,
38887+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
38888+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38889+ * GNU General Public License for more details.
38890+ *
38891+ * You should have received a copy of the GNU General Public License
523b37e3 38892+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
38893+ */
38894+
38895+#ifndef __AUFS_TYPE_H__
38896+#define __AUFS_TYPE_H__
38897+
f6c5ef8b
AM
38898+#define AUFS_NAME "aufs"
38899+
9dbd164d 38900+#ifdef __KERNEL__
f6c5ef8b
AM
38901+/*
38902+ * define it before including all other headers.
38903+ * sched.h may use pr_* macros before defining "current", so define the
38904+ * no-current version first, and re-define later.
38905+ */
38906+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
38907+#include <linux/sched.h>
38908+#undef pr_fmt
a2a7ad62
AM
38909+#define pr_fmt(fmt) \
38910+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \
38911+ (int)sizeof(current->comm), current->comm, current->pid
9dbd164d
AM
38912+#else
38913+#include <stdint.h>
38914+#include <sys/types.h>
f6c5ef8b 38915+#endif /* __KERNEL__ */
7f207e10 38916+
f6c5ef8b
AM
38917+#include <linux/limits.h>
38918+
eca34b5c 38919+#define AUFS_VERSION "5.x-rcN-20190909"
7f207e10
AM
38920+
38921+/* todo? move this to linux-2.6.19/include/magic.h */
38922+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
38923+
38924+/* ---------------------------------------------------------------------- */
38925+
38926+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 38927+typedef int8_t aufs_bindex_t;
7f207e10
AM
38928+#define AUFS_BRANCH_MAX 127
38929+#else
9dbd164d 38930+typedef int16_t aufs_bindex_t;
7f207e10
AM
38931+#ifdef CONFIG_AUFS_BRANCH_MAX_511
38932+#define AUFS_BRANCH_MAX 511
38933+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
38934+#define AUFS_BRANCH_MAX 1023
38935+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
38936+#define AUFS_BRANCH_MAX 32767
38937+#endif
38938+#endif
38939+
38940+#ifdef __KERNEL__
38941+#ifndef AUFS_BRANCH_MAX
38942+#error unknown CONFIG_AUFS_BRANCH_MAX value
38943+#endif
38944+#endif /* __KERNEL__ */
38945+
38946+/* ---------------------------------------------------------------------- */
38947+
7f207e10
AM
38948+#define AUFS_FSTYPE AUFS_NAME
38949+
38950+#define AUFS_ROOT_INO 2
38951+#define AUFS_FIRST_INO 11
38952+
38953+#define AUFS_WH_PFX ".wh."
38954+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
38955+#define AUFS_WH_TMP_LEN 4
86dc4139 38956+/* a limit for rmdir/rename a dir and copyup */
7f207e10
AM
38957+#define AUFS_MAX_NAMELEN (NAME_MAX \
38958+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
38959+ - 1 /* dot */\
38960+ - AUFS_WH_TMP_LEN) /* hex */
38961+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
38962+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
392086de
AM
38963+#define AUFS_XINO_DEF_SEC 30 /* seconds */
38964+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */
7f207e10
AM
38965+#define AUFS_DIRWH_DEF 3
38966+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 38967+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
38968+#define AUFS_RDBLK_DEF 512 /* bytes */
38969+#define AUFS_RDHASH_DEF 32
38970+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
38971+#define AUFS_MFS_DEF_SEC 30 /* seconds */
38972+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
076b876e 38973+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */
86dc4139 38974+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */
7f207e10
AM
38975+
38976+/* pseudo-link maintenace under /proc */
38977+#define AUFS_PLINK_MAINT_NAME "plink_maint"
38978+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
38979+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
38980+
8b6a4947
AM
38981+/* dirren, renamed dir */
38982+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr."
38983+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino"
38984+/* whiteouted doubly */
38985+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX
38986+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME
38987+
7f207e10
AM
38988+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
38989+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
38990+
38991+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
38992+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
38993+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
38994+
38995+/* doubly whiteouted */
38996+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
38997+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
38998+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
38999+
1e00d052 39000+/* branch permissions and attributes */
7f207e10
AM
39001+#define AUFS_BRPERM_RW "rw"
39002+#define AUFS_BRPERM_RO "ro"
39003+#define AUFS_BRPERM_RR "rr"
076b876e
AM
39004+#define AUFS_BRATTR_COO_REG "coo_reg"
39005+#define AUFS_BRATTR_COO_ALL "coo_all"
39006+#define AUFS_BRATTR_FHSM "fhsm"
39007+#define AUFS_BRATTR_UNPIN "unpin"
c1595e42
JR
39008+#define AUFS_BRATTR_ICEX "icex"
39009+#define AUFS_BRATTR_ICEX_SEC "icexsec"
39010+#define AUFS_BRATTR_ICEX_SYS "icexsys"
39011+#define AUFS_BRATTR_ICEX_TR "icextr"
39012+#define AUFS_BRATTR_ICEX_USR "icexusr"
39013+#define AUFS_BRATTR_ICEX_OTH "icexoth"
1e00d052
AM
39014+#define AUFS_BRRATTR_WH "wh"
39015+#define AUFS_BRWATTR_NLWH "nolwh"
076b876e
AM
39016+#define AUFS_BRWATTR_MOO "moo"
39017+
39018+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
39019+#define AuBrPerm_RO (1 << 1) /* readonly */
39020+#define AuBrPerm_RR (1 << 2) /* natively readonly */
39021+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
39022+
39023+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */
39024+#define AuBrAttr_COO_ALL (1 << 4)
39025+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL)
39026+
39027+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */
39028+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of
c1595e42
JR
39029+ branch. meaningless since
39030+ linux-3.18-rc1 */
39031+
39032+/* ignore error in copying XATTR */
39033+#define AuBrAttr_ICEX_SEC (1 << 7)
39034+#define AuBrAttr_ICEX_SYS (1 << 8)
39035+#define AuBrAttr_ICEX_TR (1 << 9)
39036+#define AuBrAttr_ICEX_USR (1 << 10)
39037+#define AuBrAttr_ICEX_OTH (1 << 11)
39038+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \
39039+ | AuBrAttr_ICEX_SYS \
39040+ | AuBrAttr_ICEX_TR \
39041+ | AuBrAttr_ICEX_USR \
39042+ | AuBrAttr_ICEX_OTH)
39043+
39044+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */
076b876e
AM
39045+#define AuBrRAttr_Mask AuBrRAttr_WH
39046+
c1595e42
JR
39047+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */
39048+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */
076b876e
AM
39049+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO)
39050+
39051+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO)
39052+
c1595e42 39053+/* #warning test userspace */
076b876e
AM
39054+#ifdef __KERNEL__
39055+#ifndef CONFIG_AUFS_FHSM
39056+#undef AuBrAttr_FHSM
39057+#define AuBrAttr_FHSM 0
39058+#endif
c1595e42
JR
39059+#ifndef CONFIG_AUFS_XATTR
39060+#undef AuBrAttr_ICEX
39061+#define AuBrAttr_ICEX 0
39062+#undef AuBrAttr_ICEX_SEC
39063+#define AuBrAttr_ICEX_SEC 0
39064+#undef AuBrAttr_ICEX_SYS
39065+#define AuBrAttr_ICEX_SYS 0
39066+#undef AuBrAttr_ICEX_TR
39067+#define AuBrAttr_ICEX_TR 0
39068+#undef AuBrAttr_ICEX_USR
39069+#define AuBrAttr_ICEX_USR 0
39070+#undef AuBrAttr_ICEX_OTH
39071+#define AuBrAttr_ICEX_OTH 0
39072+#endif
076b876e
AM
39073+#endif
39074+
39075+/* the longest combination */
c1595e42
JR
39076+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */
39077+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \
39078+ "+" AUFS_BRATTR_COO_REG \
39079+ "+" AUFS_BRATTR_FHSM \
39080+ "+" AUFS_BRATTR_UNPIN \
7e9cd9fe
AM
39081+ "+" AUFS_BRATTR_ICEX_SEC \
39082+ "+" AUFS_BRATTR_ICEX_SYS \
39083+ "+" AUFS_BRATTR_ICEX_USR \
39084+ "+" AUFS_BRATTR_ICEX_OTH \
076b876e
AM
39085+ "+" AUFS_BRWATTR_NLWH)
39086+
39087+typedef struct {
39088+ char a[AuBrPermStrSz];
39089+} au_br_perm_str_t;
39090+
39091+static inline int au_br_writable(int brperm)
39092+{
39093+ return brperm & AuBrPerm_RW;
39094+}
39095+
39096+static inline int au_br_whable(int brperm)
39097+{
39098+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
39099+}
39100+
39101+static inline int au_br_wh_linkable(int brperm)
39102+{
39103+ return !(brperm & AuBrWAttr_NoLinkWH);
39104+}
39105+
39106+static inline int au_br_cmoo(int brperm)
39107+{
39108+ return brperm & AuBrAttr_CMOO_Mask;
39109+}
39110+
39111+static inline int au_br_fhsm(int brperm)
39112+{
39113+ return brperm & AuBrAttr_FHSM;
39114+}
7f207e10
AM
39115+
39116+/* ---------------------------------------------------------------------- */
39117+
39118+/* ioctl */
39119+enum {
39120+ /* readdir in userspace */
39121+ AuCtl_RDU,
39122+ AuCtl_RDU_INO,
39123+
076b876e
AM
39124+ AuCtl_WBR_FD, /* pathconf wrapper */
39125+ AuCtl_IBUSY, /* busy inode */
39126+ AuCtl_MVDOWN, /* move-down */
39127+ AuCtl_BR, /* info about branches */
39128+ AuCtl_FHSM_FD /* connection for fhsm */
7f207e10
AM
39129+};
39130+
39131+/* borrowed from linux/include/linux/kernel.h */
39132+#ifndef ALIGN
eca34b5c 39133+#ifdef _GNU_SOURCE
7f207e10 39134+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
eca34b5c
AM
39135+#else
39136+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
39137+#endif
7f207e10
AM
39138+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
39139+#endif
39140+
39141+/* borrowed from linux/include/linux/compiler-gcc3.h */
39142+#ifndef __aligned
39143+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
39144+#endif
39145+
39146+#ifdef __KERNEL__
39147+#ifndef __packed
7f207e10
AM
39148+#define __packed __attribute__((packed))
39149+#endif
53392da6 39150+#endif
7f207e10
AM
39151+
39152+struct au_rdu_cookie {
9dbd164d
AM
39153+ uint64_t h_pos;
39154+ int16_t bindex;
39155+ uint8_t flags;
39156+ uint8_t pad;
39157+ uint32_t generation;
7f207e10
AM
39158+} __aligned(8);
39159+
39160+struct au_rdu_ent {
9dbd164d
AM
39161+ uint64_t ino;
39162+ int16_t bindex;
39163+ uint8_t type;
39164+ uint8_t nlen;
39165+ uint8_t wh;
7f207e10
AM
39166+ char name[0];
39167+} __aligned(8);
39168+
39169+static inline int au_rdu_len(int nlen)
39170+{
39171+ /* include the terminating NULL */
39172+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 39173+ sizeof(uint64_t));
7f207e10
AM
39174+}
39175+
39176+union au_rdu_ent_ul {
39177+ struct au_rdu_ent __user *e;
9dbd164d 39178+ uint64_t ul;
7f207e10
AM
39179+};
39180+
39181+enum {
39182+ AufsCtlRduV_SZ,
39183+ AufsCtlRduV_End
39184+};
39185+
39186+struct aufs_rdu {
39187+ /* input */
39188+ union {
9dbd164d
AM
39189+ uint64_t sz; /* AuCtl_RDU */
39190+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
39191+ };
39192+ union au_rdu_ent_ul ent;
9dbd164d 39193+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
39194+
39195+ /* input/output */
9dbd164d 39196+ uint32_t blk;
7f207e10
AM
39197+
39198+ /* output */
39199+ union au_rdu_ent_ul tail;
39200+ /* number of entries which were added in a single call */
9dbd164d
AM
39201+ uint64_t rent;
39202+ uint8_t full;
39203+ uint8_t shwh;
7f207e10
AM
39204+
39205+ struct au_rdu_cookie cookie;
39206+} __aligned(8);
39207+
1e00d052
AM
39208+/* ---------------------------------------------------------------------- */
39209+
8b6a4947
AM
39210+/* dirren. the branch is identified by the filename who contains this */
39211+struct au_drinfo {
39212+ uint64_t ino;
39213+ union {
39214+ uint8_t oldnamelen;
39215+ uint64_t _padding;
39216+ };
39217+ uint8_t oldname[0];
39218+} __aligned(8);
39219+
39220+struct au_drinfo_fdata {
39221+ uint32_t magic;
39222+ struct au_drinfo drinfo;
39223+} __aligned(8);
39224+
39225+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01)
39226+/* future */
39227+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02)
39228+
39229+/* ---------------------------------------------------------------------- */
39230+
1e00d052 39231+struct aufs_wbr_fd {
9dbd164d
AM
39232+ uint32_t oflags;
39233+ int16_t brid;
1e00d052
AM
39234+} __aligned(8);
39235+
39236+/* ---------------------------------------------------------------------- */
39237+
027c5e7a 39238+struct aufs_ibusy {
9dbd164d
AM
39239+ uint64_t ino, h_ino;
39240+ int16_t bindex;
027c5e7a
AM
39241+} __aligned(8);
39242+
1e00d052
AM
39243+/* ---------------------------------------------------------------------- */
39244+
392086de
AM
39245+/* error code for move-down */
39246+/* the actual message strings are implemented in aufs-util.git */
39247+enum {
39248+ EAU_MVDOWN_OPAQUE = 1,
39249+ EAU_MVDOWN_WHITEOUT,
39250+ EAU_MVDOWN_UPPER,
39251+ EAU_MVDOWN_BOTTOM,
39252+ EAU_MVDOWN_NOUPPER,
39253+ EAU_MVDOWN_NOLOWERBR,
39254+ EAU_Last
39255+};
39256+
c2b27bf2 39257+/* flags for move-down */
392086de
AM
39258+#define AUFS_MVDOWN_DMSG 1
39259+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */
39260+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */
39261+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */
39262+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */
39263+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */
39264+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */
39265+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */
39266+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */
076b876e
AM
39267+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */
39268+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */
39269+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */
39270+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */
c2b27bf2 39271+
076b876e 39272+/* index for move-down */
392086de
AM
39273+enum {
39274+ AUFS_MVDOWN_UPPER,
39275+ AUFS_MVDOWN_LOWER,
39276+ AUFS_MVDOWN_NARRAY
39277+};
39278+
076b876e
AM
39279+/*
39280+ * additional info of move-down
39281+ * number of free blocks and inodes.
39282+ * subset of struct kstatfs, but smaller and always 64bit.
39283+ */
39284+struct aufs_stfs {
39285+ uint64_t f_blocks;
39286+ uint64_t f_bavail;
39287+ uint64_t f_files;
39288+ uint64_t f_ffree;
39289+};
39290+
39291+struct aufs_stbr {
39292+ int16_t brid; /* optional input */
39293+ int16_t bindex; /* output */
39294+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */
39295+} __aligned(8);
39296+
c2b27bf2 39297+struct aufs_mvdown {
076b876e
AM
39298+ uint32_t flags; /* input/output */
39299+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */
39300+ int8_t au_errno; /* output */
39301+} __aligned(8);
39302+
39303+/* ---------------------------------------------------------------------- */
39304+
39305+union aufs_brinfo {
39306+ /* PATH_MAX may differ between kernel-space and user-space */
39307+ char _spacer[4096];
392086de 39308+ struct {
076b876e
AM
39309+ int16_t id;
39310+ int perm;
39311+ char path[0];
39312+ };
c2b27bf2
AM
39313+} __aligned(8);
39314+
39315+/* ---------------------------------------------------------------------- */
39316+
7f207e10
AM
39317+#define AuCtlType 'A'
39318+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
39319+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
39320+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
39321+ struct aufs_wbr_fd)
027c5e7a 39322+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
392086de
AM
39323+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \
39324+ struct aufs_mvdown)
076b876e
AM
39325+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo)
39326+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int)
7f207e10
AM
39327+
39328+#endif /* __AUFS_TYPE_H__ */
2121bcd9 39329SPDX-License-Identifier: GPL-2.0
fbc438ed 39330aufs5.x-rcN loopback patch
5527c038
JR
39331
39332diff --git a/drivers/block/loop.c b/drivers/block/loop.c
eca34b5c 39333index 80d06084b043..a83cdfec7359 100644
5527c038
JR
39334--- a/drivers/block/loop.c
39335+++ b/drivers/block/loop.c
eca34b5c 39336@@ -625,6 +625,15 @@ static inline void loop_update_dio(struct loop_device *lo)
8b6a4947 39337 lo->use_dio);
5527c038
JR
39338 }
39339
5527c038
JR
39340+static struct file *loop_real_file(struct file *file)
39341+{
39342+ struct file *f = NULL;
39343+
39344+ if (file->f_path.dentry->d_sb->s_op->real_loop)
39345+ f = file->f_path.dentry->d_sb->s_op->real_loop(file);
39346+ return f;
8b6a4947
AM
39347+}
39348+
c2c0f25c 39349 static void loop_reread_partitions(struct loop_device *lo,
8b6a4947
AM
39350 struct block_device *bdev)
39351 {
eca34b5c 39352@@ -678,6 +687,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
5527c038
JR
39353 unsigned int arg)
39354 {
e1106418 39355 struct file *file = NULL, *old_file;
5527c038 39356+ struct file *f, *virt_file = NULL, *old_virt_file;
5527c038 39357 int error;
ba1aed25 39358 bool partscan;
5527c038 39359
eca34b5c 39360@@ -697,12 +707,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
cd7a4cd9
AM
39361 file = fget(arg);
39362 if (!file)
e1106418 39363 goto out_err;
5527c038
JR
39364+ f = loop_real_file(file);
39365+ if (f) {
39366+ virt_file = file;
39367+ file = f;
39368+ get_file(file);
39369+ }
39370
cd7a4cd9
AM
39371 error = loop_validate_file(file, bdev);
39372 if (error)
e1106418 39373 goto out_err;
cd7a4cd9 39374
5527c038
JR
39375 old_file = lo->lo_backing_file;
39376+ old_virt_file = lo->lo_backing_virt_file;
39377
39378 error = -EINVAL;
39379
eca34b5c 39380@@ -714,6 +731,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
8b6a4947
AM
39381 blk_mq_freeze_queue(lo->lo_queue);
39382 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
39383 lo->lo_backing_file = file;
39384+ lo->lo_backing_virt_file = virt_file;
39385 lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
39386 mapping_set_gfp_mask(file->f_mapping,
39387 lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
eca34b5c 39388@@ -727,6 +745,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
e1106418
JR
39389 * dependency.
39390 */
5527c038
JR
39391 fput(old_file);
39392+ if (old_virt_file)
39393+ fput(old_virt_file);
e1106418 39394 if (partscan)
c2c0f25c 39395 loop_reread_partitions(lo, bdev);
5527c038 39396 return 0;
eca34b5c 39397@@ -735,6 +755,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
e1106418
JR
39398 mutex_unlock(&loop_ctl_mutex);
39399 if (file)
39400 fput(file);
5527c038
JR
39401+ if (virt_file)
39402+ fput(virt_file);
5527c038
JR
39403 return error;
39404 }
e1106418 39405
eca34b5c 39406@@ -939,7 +961,7 @@ static void loop_update_rotational(struct loop_device *lo)
5527c038
JR
39407 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
39408 struct block_device *bdev, unsigned int arg)
39409 {
062440b3 39410- struct file *file;
5527c038
JR
39411+ struct file *file, *f, *virt_file = NULL;
39412 struct inode *inode;
39413 struct address_space *mapping;
eca34b5c
AM
39414 struct block_device *claimed_bdev = NULL;
39415@@ -955,6 +977,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
5527c038
JR
39416 file = fget(arg);
39417 if (!file)
39418 goto out;
39419+ f = loop_real_file(file);
39420+ if (f) {
39421+ virt_file = file;
39422+ file = f;
39423+ get_file(file);
39424+ }
39425
fbc438ed
JR
39426 /*
39427 * If we don't hold exclusive handle for the device, upgrade to it
eca34b5c 39428@@ -1003,6 +1031,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
5527c038
JR
39429 lo->lo_device = bdev;
39430 lo->lo_flags = lo_flags;
39431 lo->lo_backing_file = file;
39432+ lo->lo_backing_virt_file = virt_file;
39433 lo->transfer = NULL;
39434 lo->ioctl = NULL;
39435 lo->lo_sizelimit = 0;
eca34b5c
AM
39436@@ -1046,6 +1075,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
39437 bd_abort_claiming(bdev, claimed_bdev, loop_set_fd);
e1106418 39438 out_putf:
5527c038
JR
39439 fput(file);
39440+ if (virt_file)
39441+ fput(virt_file);
e1106418 39442 out:
5527c038
JR
39443 /* This is safe: open() is still holding a reference. */
39444 module_put(THIS_MODULE);
eca34b5c 39445@@ -1092,6 +1123,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
ba1aed25 39446 static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39447 {
e1106418 39448 struct file *filp = NULL;
5527c038
JR
39449+ struct file *virt_filp = lo->lo_backing_virt_file;
39450 gfp_t gfp = lo->old_gfp_mask;
39451 struct block_device *bdev = lo->lo_device;
ba1aed25 39452 int err = 0;
eca34b5c 39453@@ -1115,6 +1147,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39454
5527c038 39455 spin_lock_irq(&lo->lo_lock);
5527c038
JR
39456 lo->lo_backing_file = NULL;
39457+ lo->lo_backing_virt_file = NULL;
39458 spin_unlock_irq(&lo->lo_lock);
39459
39460 loop_release_xfer(lo);
eca34b5c 39461@@ -1197,6 +1230,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39462 */
e1106418
JR
39463 if (filp)
39464 fput(filp);
5527c038
JR
39465+ if (virt_filp)
39466+ fput(virt_filp);
e1106418 39467 return err;
5527c038
JR
39468 }
39469
39470diff --git a/drivers/block/loop.h b/drivers/block/loop.h
ba1aed25 39471index af75a5ee4094..1e6ee5a4f623 100644
5527c038
JR
39472--- a/drivers/block/loop.h
39473+++ b/drivers/block/loop.h
39474@@ -46,7 +46,7 @@ struct loop_device {
39475 int (*ioctl)(struct loop_device *, int cmd,
39476 unsigned long arg);
39477
39478- struct file * lo_backing_file;
39479+ struct file * lo_backing_file, *lo_backing_virt_file;
39480 struct block_device *lo_device;
5527c038 39481 void *key_data;
8b6a4947 39482
5527c038 39483diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
ba1aed25 39484index 0309f0d502ff..19feb4f3cb5f 100644
5527c038
JR
39485--- a/fs/aufs/f_op.c
39486+++ b/fs/aufs/f_op.c
acd2b654 39487@@ -359,7 +359,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
5527c038
JR
39488 if (IS_ERR(h_file))
39489 goto out;
39490
39491- if (au_test_loopback_kthread()) {
39492+ if (0 && au_test_loopback_kthread()) {
39493 au_warn_loopback(h_file->f_path.dentry->d_sb);
39494 if (file->f_mapping != h_file->f_mapping) {
39495 file->f_mapping = h_file->f_mapping;
39496diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
fbc438ed 39497index 9ba35a878ecd..4ed0ff03d5ab 100644
5527c038
JR
39498--- a/fs/aufs/loop.c
39499+++ b/fs/aufs/loop.c
2121bcd9 39500@@ -133,3 +133,19 @@ void au_loopback_fin(void)
79b8bda9 39501 symbol_put(loop_backing_file);
9f237c51 39502 au_kfree_try_rcu(au_warn_loopback_array);
5527c038
JR
39503 }
39504+
39505+/* ---------------------------------------------------------------------- */
39506+
39507+/* support the loopback block device insude aufs */
39508+
39509+struct file *aufs_real_loop(struct file *file)
39510+{
39511+ struct file *f;
39512+
39513+ BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb));
39514+ fi_read_lock(file);
39515+ f = au_hf_top(file);
39516+ fi_read_unlock(file);
39517+ AuDebugOn(!f);
39518+ return f;
39519+}
39520diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
83b672a5 39521index f31e40aff267..e13fb1a0717a 100644
5527c038
JR
39522--- a/fs/aufs/loop.h
39523+++ b/fs/aufs/loop.h
eca801bf 39524@@ -26,6 +26,8 @@ void au_warn_loopback(struct super_block *h_sb);
5527c038
JR
39525
39526 int au_loopback_init(void);
39527 void au_loopback_fin(void);
39528+
39529+struct file *aufs_real_loop(struct file *file);
39530 #else
83b672a5 39531 AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf
AM
39532
39533@@ -36,6 +38,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb)
5527c038
JR
39534
39535 AuStubInt0(au_loopback_init, void)
39536 AuStubVoid(au_loopback_fin, void)
39537+
39538+AuStub(struct file *, aufs_real_loop, return NULL, struct file *file)
39539 #endif /* BLK_DEV_LOOP */
39540
39541 #endif /* __KERNEL__ */
39542diff --git a/fs/aufs/super.c b/fs/aufs/super.c
fbc438ed 39543index a97e2921cb09..f74eb6962684 100644
5527c038
JR
39544--- a/fs/aufs/super.c
39545+++ b/fs/aufs/super.c
fbc438ed 39546@@ -844,7 +844,10 @@ static const struct super_operations aufs_sop = {
5527c038
JR
39547 .statfs = aufs_statfs,
39548 .put_super = aufs_put_super,
39549 .sync_fs = aufs_sync_fs,
39550- .remount_fs = aufs_remount_fs
39551+ .remount_fs = aufs_remount_fs,
39552+#ifdef CONFIG_AUFS_BDEV_LOOP
39553+ .real_loop = aufs_real_loop
39554+#endif
39555 };
39556
39557 /* ---------------------------------------------------------------------- */
39558diff --git a/include/linux/fs.h b/include/linux/fs.h
eca34b5c 39559index 3dbec51c2037..38ab7b6c7c6d 100644
5527c038
JR
39560--- a/include/linux/fs.h
39561+++ b/include/linux/fs.h
eca34b5c 39562@@ -1948,6 +1948,10 @@ struct super_operations {
5527c038
JR
39563 struct shrink_control *);
39564 long (*free_cached_objects)(struct super_block *,
39565 struct shrink_control *);
39566+#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
39567+ /* and aufs */
39568+ struct file *(*real_loop)(struct file *);
39569+#endif
39570 };
39571
39572 /*
This page took 6.728989 seconds and 4 git commands to generate.