]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs5.patch
- up to 5.2.14
[packages/kernel.git] / kernel-aufs5.patch
CommitLineData
2121bcd9 1SPDX-License-Identifier: GPL-2.0
fbc438ed 2aufs5.x-rcN kbuild patch
7f207e10 3
fbc438ed
JR
4diff --git a/fs/Kconfig b/fs/Kconfig
5index f1046cf6ad85..95c957c2e2c3 100644
6--- a/fs/Kconfig
7+++ b/fs/Kconfig
8@@ -262,6 +262,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
fbc438ed 17index c9aea23aba56..57c6f47b0185 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
fbc438ed 29index a6954776a37e..c30c2d323711 100644
c1595e42
JR
30--- a/MAINTAINERS
31+++ b/MAINTAINERS
fbc438ed 32@@ -2769,6 +2769,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
fbc438ed 53index f11b7dc16e9d..1b723737592b 100644
392086de
AM
54--- a/drivers/block/loop.c
55+++ b/drivers/block/loop.c
fbc438ed 56@@ -746,6 +746,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
fbc438ed 82index c435398f2c81..a688a042d022 100644
c1595e42
JR
83--- a/fs/dcache.c
84+++ b/fs/dcache.c
ba1aed25 85@@ -1247,7 +1247,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
fbc438ed 117index df6542ec3b88..407d7b45e2ee 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
fbc438ed 130index b26778bdc236..b460383a4228 100644
8b6a4947
AM
131--- a/fs/namespace.c
132+++ b/fs/namespace.c
fbc438ed 133@@ -770,6 +770,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
fbc438ed 147index c543d965e288..35ab54e0a994 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
fbc438ed 180index 14cb602d9a2f..58d2692c5f30 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
fbc438ed 221index f7fdfe93e25d..28593b894e7b 100644
5527c038
JR
222--- a/include/linux/fs.h
223+++ b/include/linux/fs.h
fbc438ed 224@@ -1333,6 +1333,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);
fbc438ed 232@@ -1812,6 +1813,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);
fbc438ed 240@@ -1882,6 +1884,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 *);
fbc438ed 253@@ -2315,6 +2323,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;
fbc438ed 261@@ -2603,6 +2612,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
fbc438ed 270index 6e2377e6c1d6..5a945d18a72a 100644
8b6a4947
AM
271--- a/include/linux/lockdep.h
272+++ b/include/linux/lockdep.h
fbc438ed 273@@ -325,6 +325,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 *
fbc438ed 282@@ -463,6 +465,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
fbc438ed 325index c47788fa85f9..3c35a1059890 100644
8b6a4947
AM
326--- a/kernel/locking/lockdep.c
327+++ b/kernel/locking/lockdep.c
fbc438ed 328@@ -152,7 +152,7 @@ static
ba1aed25 329 #endif
9f237c51 330 struct lock_class lock_classes[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 {
335 if (!hlock->class_idx) {
336 /*
fbc438ed 337@@ -163,6 +163,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
8b6a4947
AM
338 }
339 return lock_classes + hlock->class_idx - 1;
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
fbc438ed 349index 9c8ca6cd3ce4..2ae2c94aceca 100644
c1595e42
JR
350--- a/fs/proc/base.c
351+++ b/fs/proc/base.c
eca801bf 352@@ -2014,7 +2014,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
c1595e42
JR
353 down_read(&mm->mmap_sem);
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
fbc438ed 378index 01d4eb0e6bd1..fedfaa012768 100644
fb47a38f
JR
379--- a/fs/proc/task_mmu.c
380+++ b/fs/proc/task_mmu.c
acd2b654 381@@ -305,7 +305,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;
fbc438ed 393@@ -1761,7 +1764,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
fbc438ed 403index 36bf0f2e102e..8df6cbc58756 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
fbc438ed 419index 0e8834ac32b7..b3f42f01aaf0 100644
fb47a38f
JR
420--- a/include/linux/mm.h
421+++ b/include/linux/mm.h
fbc438ed 422@@ -1542,6 +1542,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
fbc438ed 452index 8ec38b11b361..d3f5492a2611 100644
fb47a38f
JR
453--- a/include/linux/mm_types.h
454+++ b/include/linux/mm_types.h
fbc438ed 455@@ -253,6 +253,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
fbc438ed 463@@ -327,6 +328,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
8b6a4947 470 atomic_long_t swap_readahead_info;
fb47a38f 471diff --git a/kernel/fork.c b/kernel/fork.c
fbc438ed 472index 75675b9bf6df..dc333a5e6926 100644
fb47a38f
JR
473--- a/kernel/fork.c
474+++ b/kernel/fork.c
fbc438ed 475@@ -549,7 +549,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
fbc438ed 485index ac5e5ba78874..5decb22d13a0 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 \
7e9cd9fe
AM
492- debug.o $(mmu-y)
493+ prfile.o debug.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
fbc438ed 498index df2006ba0cfa..d5221dedfe56 100644
fb47a38f
JR
499--- a/mm/filemap.c
500+++ b/mm/filemap.c
fbc438ed 501@@ -2671,7 +2671,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
fbc438ed 608index d8c02fbe03b5..22dae8b7216a 100644
fb47a38f
JR
609--- a/mm/nommu.c
610+++ b/mm/nommu.c
fbc438ed 611@@ -640,7 +640,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 */
fbc438ed 620@@ -778,7 +778,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 }
fbc438ed 629@@ -1301,7 +1301,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;
fbc438ed 638@@ -1376,10 +1376,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
fbc438ed 747index a688a042d022..3fc74e471924 100644
c1595e42
JR
748--- a/fs/dcache.c
749+++ b/fs/dcache.c
ba1aed25 750@@ -1352,6 +1352,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;
fbc438ed 758@@ -2850,6 +2851,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
fbc438ed 767index 89a500bb897a..1a722915ed77 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
fbc438ed 819index 407d7b45e2ee..b4d3e100abd0 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
fbc438ed 831index b460383a4228..b74d15701ed7 100644
7f207e10
AM
832--- a/fs/namespace.c
833+++ b/fs/namespace.c
fbc438ed 834@@ -436,6 +436,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
fbc438ed 842@@ -775,6 +776,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
fbc438ed 850@@ -1908,6 +1910,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
fbc438ed 887index 25eb247ea85a..6a2a2f722eae 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.
fbc438ed 906@@ -677,6 +679,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
fbc438ed 914@@ -801,6 +804,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
fbc438ed 923index b5b80469b93d..eb818f6b9519 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
fbc438ed 935index 35ab54e0a994..9da238d64ea4 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
fbc438ed 971index 58d2692c5f30..4fe4afa7f6b1 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
fbc438ed 1015index 3c35a1059890..67dccde036a2 100644
8b6a4947
AM
1016--- a/kernel/locking/lockdep.c
1017+++ b/kernel/locking/lockdep.c
fbc438ed 1018@@ -163,6 +163,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
8b6a4947
AM
1019 }
1020 return lock_classes + hlock->class_idx - 1;
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
fbc438ed 1036index dc28914fa72e..c2ddfea2b280 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
fbc438ed 1045index f493db0bf62a..96f118be469f 100644
7f207e10
AM
1046--- a/security/security.c
1047+++ b/security/security.c
fbc438ed 1048@@ -993,6 +993,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 {
fbc438ed 1056@@ -1009,6 +1010,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)
fbc438ed 1064@@ -1017,6 +1019,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,
fbc438ed 1072@@ -1044,6 +1047,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 {
fbc438ed 1080@@ -1051,6 +1055,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 {
fbc438ed 1088@@ -1058,6 +1063,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 {
fbc438ed 1096@@ -1158,6 +1164,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 {
fbc438ed 1104@@ -1335,6 +1342,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
fbc438ed
JR
1113--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 08:00:00.000000000 +0800
1114+++ linux/Documentation/ABI/testing/debugfs-aufs 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
1172--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 08:00:00.000000000 +0800
1173+++ linux/Documentation/ABI/testing/sysfs-aufs 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
1207--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 08:00:00.000000000 +0800
1208+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
1382--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 08:00:00.000000000 +0800
1383+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
1644--- /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 08:00:00.000000000 +0800
1645+++ linux/Documentation/filesystems/aufs/design/03atomic_open.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
1733--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 08:00:00.000000000 +0800
1734+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
1850--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 08:00:00.000000000 +0800
1851+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
1928--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 08:00:00.000000000 +0800
1929+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
1996--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 08:00:00.000000000 +0800
1997+++ linux/Documentation/filesystems/aufs/design/06dirren.dot 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
2031--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 08:00:00.000000000 +0800
2032+++ linux/Documentation/filesystems/aufs/design/06dirren.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
2137--- /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 08:00:00.000000000 +0800
2138+++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
2261--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 08:00:00.000000000 +0800
2262+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
2337--- /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 08:00:00.000000000 +0800
2338+++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
2437--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 08:00:00.000000000 +0800
2438+++ linux/Documentation/filesystems/aufs/design/07export.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
2499--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 08:00:00.000000000 +0800
2500+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
2555--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 08:00:00.000000000 +0800
2556+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
2606--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 08:00:00.000000000 +0800
2607+++ linux/Documentation/filesystems/aufs/README 2019-07-11 21:21:54.375717654 +0800
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
fbc438ed
JR
3009--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 08:00:00.000000000 +0800
3010+++ linux/fs/aufs/aufs.h 2019-07-11 21:21:54.379051070 +0800
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
fbc438ed
JR
3075--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 08:00:00.000000000 +0800
3076+++ linux/fs/aufs/branch.c 2019-07-11 21:21:54.379051070 +0800
ba1aed25 3077@@ -0,0 +1,1423 @@
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;
1facf9fc 4298+
027c5e7a
AM
4299+ mnt_flags = au_mntflags(sb);
4300+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
4301+
7f207e10
AM
4302+ array = au_farray_alloc(sb, &max);
4303+ err = PTR_ERR(array);
4304+ if (IS_ERR(array))
1facf9fc 4305+ goto out;
4306+
7f207e10 4307+ do_warn = 0;
e49829fe 4308+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
4309+ for (ull = 0; ull < max; ull++) {
4310+ file = array[ull];
076b876e
AM
4311+ if (unlikely(!file))
4312+ break;
1facf9fc 4313+
523b37e3 4314+ /* AuDbg("%pD\n", file); */
1facf9fc 4315+ fi_read_lock(file);
4316+ if (unlikely(au_test_mmapped(file))) {
4317+ err = -EBUSY;
523b37e3 4318+ AuVerbose(verbose, "mmapped %pD\n", file);
7f207e10 4319+ AuDbgFile(file);
1facf9fc 4320+ FiMustNoWaiters(file);
4321+ fi_read_unlock(file);
7f207e10 4322+ goto out_array;
1facf9fc 4323+ }
4324+
e49829fe
JR
4325+ hfile = &au_fi(file)->fi_htop;
4326+ hf = hfile->hf_file;
7e9cd9fe 4327+ if (!d_is_reg(file->f_path.dentry)
1facf9fc 4328+ || !(file->f_mode & FMODE_WRITE)
e49829fe 4329+ || hfile->hf_br->br_id != br_id
7f207e10
AM
4330+ || !(hf->f_mode & FMODE_WRITE))
4331+ array[ull] = NULL;
4332+ else {
4333+ do_warn = 1;
4334+ get_file(file);
1facf9fc 4335+ }
4336+
1facf9fc 4337+ FiMustNoWaiters(file);
4338+ fi_read_unlock(file);
7f207e10
AM
4339+ fput(file);
4340+ }
1facf9fc 4341+
4342+ err = 0;
7f207e10 4343+ if (do_warn)
dece6358 4344+ au_warn_ima();
7f207e10
AM
4345+
4346+ for (ull = 0; ull < max; ull++) {
4347+ file = array[ull];
4348+ if (!file)
4349+ continue;
4350+
1facf9fc 4351+ /* todo: already flushed? */
523b37e3
AM
4352+ /*
4353+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its
4354+ * approach which resets f_mode and calls mnt_drop_write() and
4355+ * file_release_write() for each file, because the branch
4356+ * attribute in aufs world is totally different from the native
4357+ * fs rw/ro mode.
4358+ */
7f207e10
AM
4359+ /* fi_read_lock(file); */
4360+ hfile = &au_fi(file)->fi_htop;
4361+ hf = hfile->hf_file;
4362+ /* fi_read_unlock(file); */
027c5e7a 4363+ spin_lock(&hf->f_lock);
38d290e6
JR
4364+ writer = !!(hf->f_mode & FMODE_WRITER);
4365+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER);
027c5e7a 4366+ spin_unlock(&hf->f_lock);
38d290e6
JR
4367+ if (writer) {
4368+ put_write_access(file_inode(hf));
c06a8ce3 4369+ __mnt_drop_write(hf->f_path.mnt);
1facf9fc 4370+ }
4371+ }
4372+
7f207e10
AM
4373+out_array:
4374+ au_farray_free(array, max);
4f0767ce 4375+out:
7f207e10 4376+ AuTraceErr(err);
1facf9fc 4377+ return err;
4378+}
4379+
4380+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4381+ int *do_refresh)
1facf9fc 4382+{
4383+ int err, rerr;
4384+ aufs_bindex_t bindex;
4385+ struct dentry *root;
4386+ struct au_branch *br;
076b876e 4387+ struct au_br_fhsm *bf;
1facf9fc 4388+
4389+ root = sb->s_root;
1facf9fc 4390+ bindex = au_find_dbindex(root, mod->h_root);
4391+ if (bindex < 0) {
4392+ if (remount)
4393+ return 0; /* success */
4394+ err = -ENOENT;
4a4d8108 4395+ pr_err("%s no such branch\n", mod->path);
1facf9fc 4396+ goto out;
4397+ }
4398+ AuDbg("bindex b%d\n", bindex);
4399+
5527c038 4400+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path);
1facf9fc 4401+ if (unlikely(err))
4402+ goto out;
4403+
4404+ br = au_sbr(sb, bindex);
86dc4139 4405+ AuDebugOn(mod->h_root != au_br_dentry(br));
1facf9fc 4406+ if (br->br_perm == mod->perm)
4407+ return 0; /* success */
4408+
076b876e
AM
4409+ /* pre-allocate for non-fhsm --> fhsm */
4410+ bf = NULL;
4411+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) {
4412+ err = au_fhsm_br_alloc(br);
4413+ if (unlikely(err))
4414+ goto out;
4415+ bf = br->br_fhsm;
4416+ br->br_fhsm = NULL;
4417+ }
4418+
1facf9fc 4419+ if (au_br_writable(br->br_perm)) {
4420+ /* remove whiteout base */
86dc4139 4421+ err = au_br_init_wh(sb, br, mod->perm);
1facf9fc 4422+ if (unlikely(err))
076b876e 4423+ goto out_bf;
1facf9fc 4424+
4425+ if (!au_br_writable(mod->perm)) {
4426+ /* rw --> ro, file might be mmapped */
4427+ DiMustNoWaiters(root);
5527c038 4428+ IiMustNoWaiters(d_inode(root));
1facf9fc 4429+ di_write_unlock(root);
4430+ err = au_br_mod_files_ro(sb, bindex);
4431+ /* aufs_write_lock() calls ..._child() */
4432+ di_write_lock_child(root);
4433+
4434+ if (unlikely(err)) {
4435+ rerr = -ENOMEM;
be52b249 4436+ br->br_wbr = kzalloc(sizeof(*br->br_wbr),
1facf9fc 4437+ GFP_NOFS);
86dc4139
AM
4438+ if (br->br_wbr)
4439+ rerr = au_wbr_init(br, sb, br->br_perm);
1facf9fc 4440+ if (unlikely(rerr)) {
4441+ AuIOErr("nested error %d (%d)\n",
4442+ rerr, err);
4443+ br->br_perm = mod->perm;
4444+ }
4445+ }
4446+ }
4447+ } else if (au_br_writable(mod->perm)) {
4448+ /* ro --> rw */
4449+ err = -ENOMEM;
be52b249 4450+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS);
1facf9fc 4451+ if (br->br_wbr) {
86dc4139 4452+ err = au_wbr_init(br, sb, mod->perm);
1facf9fc 4453+ if (unlikely(err)) {
9f237c51 4454+ au_kfree_rcu(br->br_wbr);
1facf9fc 4455+ br->br_wbr = NULL;
4456+ }
4457+ }
4458+ }
076b876e
AM
4459+ if (unlikely(err))
4460+ goto out_bf;
4461+
4462+ if (au_br_fhsm(br->br_perm)) {
4463+ if (!au_br_fhsm(mod->perm)) {
4464+ /* fhsm --> non-fhsm */
4465+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 4466+ au_kfree_rcu(br->br_fhsm);
076b876e
AM
4467+ br->br_fhsm = NULL;
4468+ }
4469+ } else if (au_br_fhsm(mod->perm))
4470+ /* non-fhsm --> fhsm */
4471+ br->br_fhsm = bf;
4472+
076b876e
AM
4473+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
4474+ br->br_perm = mod->perm;
4475+ goto out; /* success */
1facf9fc 4476+
076b876e 4477+out_bf:
9f237c51 4478+ au_kfree_try_rcu(bf);
076b876e
AM
4479+out:
4480+ AuTraceErr(err);
4481+ return err;
4482+}
4483+
4484+/* ---------------------------------------------------------------------- */
4485+
4486+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs)
4487+{
4488+ int err;
4489+ struct kstatfs kstfs;
4490+
4491+ err = vfs_statfs(&br->br_path, &kstfs);
1facf9fc 4492+ if (!err) {
076b876e
AM
4493+ stfs->f_blocks = kstfs.f_blocks;
4494+ stfs->f_bavail = kstfs.f_bavail;
4495+ stfs->f_files = kstfs.f_files;
4496+ stfs->f_ffree = kstfs.f_ffree;
1facf9fc 4497+ }
4498+
1facf9fc 4499+ return err;
4500+}
7f207e10 4501diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
fbc438ed
JR
4502--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 08:00:00.000000000 +0800
4503+++ linux/fs/aufs/branch.h 2019-07-11 21:21:54.379051070 +0800
83b672a5 4504@@ -0,0 +1,366 @@
062440b3 4505+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 4506+/*
ba1aed25 4507+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 4508+ *
4509+ * This program, aufs is free software; you can redistribute it and/or modify
4510+ * it under the terms of the GNU General Public License as published by
4511+ * the Free Software Foundation; either version 2 of the License, or
4512+ * (at your option) any later version.
dece6358
AM
4513+ *
4514+ * This program is distributed in the hope that it will be useful,
4515+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4516+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4517+ * GNU General Public License for more details.
4518+ *
4519+ * You should have received a copy of the GNU General Public License
523b37e3 4520+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4521+ */
4522+
4523+/*
4524+ * branch filesystems and xino for them
4525+ */
4526+
4527+#ifndef __AUFS_BRANCH_H__
4528+#define __AUFS_BRANCH_H__
4529+
4530+#ifdef __KERNEL__
4531+
1facf9fc 4532+#include <linux/mount.h>
8b6a4947 4533+#include "dirren.h"
4a4d8108 4534+#include "dynop.h"
acd2b654 4535+#include "lcnt.h"
1facf9fc 4536+#include "rwsem.h"
4537+#include "super.h"
4538+
4539+/* ---------------------------------------------------------------------- */
4540+
4541+/* a xino file */
062440b3 4542+struct au_xino {
acd2b654
AM
4543+ struct file **xi_file;
4544+ unsigned int xi_nfile;
4545+
521ced18
JR
4546+ struct {
4547+ spinlock_t spin;
4548+ ino_t *array;
4549+ int total;
4550+ /* reserved for future use */
4551+ /* unsigned long *bitmap; */
4552+ wait_queue_head_t wqh;
4553+ } xi_nondir;
1facf9fc 4554+
acd2b654 4555+ struct mutex xi_mtx; /* protects xi_file array */
9f237c51 4556+ struct hlist_bl_head xi_writing;
acd2b654 4557+
062440b3 4558+ atomic_t xi_truncating;
1facf9fc 4559+
062440b3 4560+ struct kref xi_kref;
1facf9fc 4561+};
4562+
076b876e
AM
4563+/* File-based Hierarchical Storage Management */
4564+struct au_br_fhsm {
4565+#ifdef CONFIG_AUFS_FHSM
4566+ struct mutex bf_lock;
4567+ unsigned long bf_jiffy;
4568+ struct aufs_stfs bf_stfs;
4569+ int bf_readable;
4570+#endif
4571+};
4572+
1facf9fc 4573+/* members for writable branch only */
4574+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
4575+struct au_wbr {
dece6358 4576+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 4577+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 4578+ atomic_t wbr_wh_running;
1facf9fc 4579+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
4580+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
4581+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
4582+
4583+ /* mfs mode */
4584+ unsigned long long wbr_bytes;
4585+};
4586+
4a4d8108
AM
4587+/* ext2 has 3 types of operations at least, ext3 has 4 */
4588+#define AuBrDynOp (AuDyLast * 4)
4589+
1716fcea
AM
4590+#ifdef CONFIG_AUFS_HFSNOTIFY
4591+/* support for asynchronous destruction */
4592+struct au_br_hfsnotify {
4593+ struct fsnotify_group *hfsn_group;
4594+};
4595+#endif
4596+
392086de
AM
4597+/* sysfs entries */
4598+struct au_brsysfs {
4599+ char name[16];
4600+ struct attribute attr;
4601+};
4602+
4603+enum {
4604+ AuBrSysfs_BR,
4605+ AuBrSysfs_BRID,
4606+ AuBrSysfs_Last
4607+};
4608+
1facf9fc 4609+/* protected by superblock rwsem */
4610+struct au_branch {
062440b3 4611+ struct au_xino *br_xino;
1facf9fc 4612+
4613+ aufs_bindex_t br_id;
4614+
4615+ int br_perm;
86dc4139 4616+ struct path br_path;
4a4d8108
AM
4617+ spinlock_t br_dykey_lock;
4618+ struct au_dykey *br_dykey[AuBrDynOp];
acd2b654
AM
4619+ au_lcnt_t br_nfiles; /* opened files */
4620+ au_lcnt_t br_count; /* in-use for other */
1facf9fc 4621+
4622+ struct au_wbr *br_wbr;
076b876e 4623+ struct au_br_fhsm *br_fhsm;
1facf9fc 4624+
027c5e7a 4625+#ifdef CONFIG_AUFS_HFSNOTIFY
1716fcea 4626+ struct au_br_hfsnotify *br_hfsn;
027c5e7a
AM
4627+#endif
4628+
1facf9fc 4629+#ifdef CONFIG_SYSFS
392086de
AM
4630+ /* entries under sysfs per mount-point */
4631+ struct au_brsysfs br_sysfs[AuBrSysfs_Last];
1facf9fc 4632+#endif
8b6a4947 4633+
062440b3
AM
4634+#ifdef CONFIG_DEBUG_FS
4635+ struct dentry *br_dbgaufs; /* xino */
4636+#endif
4637+
8b6a4947 4638+ struct au_dr_br br_dirren;
1facf9fc 4639+};
4640+
4641+/* ---------------------------------------------------------------------- */
4642+
86dc4139
AM
4643+static inline struct vfsmount *au_br_mnt(struct au_branch *br)
4644+{
4645+ return br->br_path.mnt;
4646+}
4647+
4648+static inline struct dentry *au_br_dentry(struct au_branch *br)
4649+{
4650+ return br->br_path.dentry;
4651+}
4652+
4653+static inline struct super_block *au_br_sb(struct au_branch *br)
4654+{
4655+ return au_br_mnt(br)->mnt_sb;
4656+}
4657+
1facf9fc 4658+static inline int au_br_rdonly(struct au_branch *br)
4659+{
8b6a4947 4660+ return (sb_rdonly(au_br_sb(br))
1facf9fc 4661+ || !au_br_writable(br->br_perm))
4662+ ? -EROFS : 0;
4663+}
4664+
4a4d8108 4665+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 4666+{
4a4d8108 4667+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 4668+ return !(brperm & AuBrPerm_RR);
1facf9fc 4669+#else
4670+ return 0;
4671+#endif
4672+}
4673+
b912730e
AM
4674+static inline int au_br_test_oflag(int oflag, struct au_branch *br)
4675+{
4676+ int err, exec_flag;
4677+
4678+ err = 0;
4679+ exec_flag = oflag & __FMODE_EXEC;
79b8bda9 4680+ if (unlikely(exec_flag && path_noexec(&br->br_path)))
b912730e
AM
4681+ err = -EACCES;
4682+
4683+ return err;
4684+}
4685+
062440b3
AM
4686+static inline void au_xino_get(struct au_branch *br)
4687+{
4688+ struct au_xino *xi;
4689+
4690+ xi = br->br_xino;
4691+ if (xi)
4692+ kref_get(&xi->xi_kref);
4693+}
4694+
4695+static inline int au_xino_count(struct au_branch *br)
4696+{
4697+ int v;
4698+ struct au_xino *xi;
4699+
4700+ v = 0;
4701+ xi = br->br_xino;
4702+ if (xi)
4703+ v = kref_read(&xi->xi_kref);
4704+
4705+ return v;
4706+}
4707+
1facf9fc 4708+/* ---------------------------------------------------------------------- */
4709+
4710+/* branch.c */
4711+struct au_sbinfo;
4712+void au_br_free(struct au_sbinfo *sinfo);
4713+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
4714+struct au_opt_add;
4715+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
4716+struct au_opt_del;
4717+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
4718+long au_ibusy_ioctl(struct file *file, unsigned long arg);
4719+#ifdef CONFIG_COMPAT
4720+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
4721+#endif
1facf9fc 4722+struct au_opt_mod;
4723+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4724+ int *do_refresh);
076b876e
AM
4725+struct aufs_stfs;
4726+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
1facf9fc 4727+
4728+/* xino.c */
4729+static const loff_t au_loff_max = LLONG_MAX;
4730+
acd2b654 4731+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry);
83b672a5
AM
4732+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
4733+ int wbrtop);
062440b3
AM
4734+struct file *au_xino_create2(struct super_block *sb, struct path *base,
4735+ struct file *copy_src);
acd2b654
AM
4736+struct au_xi_new {
4737+ struct au_xino *xi; /* switch between xino and xigen */
4738+ int idx;
4739+ struct path *base;
4740+ struct file *copy_src;
4741+};
4742+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew);
062440b3
AM
4743+
4744+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4745+ ino_t *ino);
4746+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4747+ ino_t ino);
5527c038 4748+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size,
1facf9fc 4749+ loff_t *pos);
5527c038
JR
4750+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
4751+ size_t size, loff_t *pos);
062440b3
AM
4752+
4753+int au_xib_trunc(struct super_block *sb);
acd2b654 4754+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin);
1facf9fc 4755+
acd2b654 4756+struct au_xino *au_xino_alloc(unsigned int nfile);
062440b3 4757+int au_xino_put(struct au_branch *br);
acd2b654 4758+struct file *au_xino_file1(struct au_xino *xi);
062440b3 4759+
1facf9fc 4760+struct au_opt_xino;
1facf9fc 4761+void au_xino_clr(struct super_block *sb);
062440b3 4762+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount);
1facf9fc 4763+struct file *au_xino_def(struct super_block *sb);
062440b3
AM
4764+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino,
4765+ struct path *base);
4766+
4767+ino_t au_xino_new_ino(struct super_block *sb);
4768+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 4769+
521ced18
JR
4770+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
4771+ ino_t h_ino, int idx);
4772+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4773+ int *idx);
4774+
062440b3
AM
4775+int au_xino_path(struct seq_file *seq, struct file *file);
4776+
1facf9fc 4777+/* ---------------------------------------------------------------------- */
4778+
acd2b654
AM
4779+/* @idx is signed to accept -1 meaning the first file */
4780+static inline struct file *au_xino_file(struct au_xino *xi, int idx)
4781+{
4782+ struct file *file;
4783+
4784+ file = NULL;
4785+ if (!xi)
4786+ goto out;
4787+
4788+ if (idx >= 0) {
4789+ if (idx < xi->xi_nfile)
4790+ file = xi->xi_file[idx];
4791+ } else
4792+ file = au_xino_file1(xi);
4793+
4794+out:
4795+ return file;
4796+}
4797+
4798+/* ---------------------------------------------------------------------- */
4799+
1facf9fc 4800+/* Superblock to branch */
4801+static inline
4802+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
4803+{
4804+ return au_sbr(sb, bindex)->br_id;
4805+}
4806+
4807+static inline
4808+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
4809+{
86dc4139 4810+ return au_br_mnt(au_sbr(sb, bindex));
1facf9fc 4811+}
4812+
4813+static inline
4814+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
4815+{
86dc4139 4816+ return au_br_sb(au_sbr(sb, bindex));
1facf9fc 4817+}
4818+
1facf9fc 4819+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
4820+{
4821+ return au_sbr(sb, bindex)->br_perm;
4822+}
4823+
4824+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
4825+{
4826+ return au_br_whable(au_sbr_perm(sb, bindex));
4827+}
4828+
4829+/* ---------------------------------------------------------------------- */
4830+
8b6a4947
AM
4831+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem)
4832+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem)
4833+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem)
4834+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem)
1facf9fc 4835+/*
8b6a4947
AM
4836+#define wbr_wh_read_trylock_nested(wbr) \
4837+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem)
4838+#define wbr_wh_write_trylock_nested(wbr) \
4839+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem)
4840+*/
1facf9fc 4841+
8b6a4947
AM
4842+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem)
4843+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem)
4844+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem)
4845+
4846+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem)
4847+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem)
4848+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem)
dece6358 4849+
076b876e
AM
4850+/* ---------------------------------------------------------------------- */
4851+
4852+#ifdef CONFIG_AUFS_FHSM
4853+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm)
4854+{
4855+ mutex_init(&brfhsm->bf_lock);
4856+ brfhsm->bf_jiffy = 0;
4857+ brfhsm->bf_readable = 0;
4858+}
4859+
4860+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm)
4861+{
4862+ mutex_destroy(&brfhsm->bf_lock);
4863+}
4864+#else
4865+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm)
4866+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm)
4867+#endif
4868+
1facf9fc 4869+#endif /* __KERNEL__ */
4870+#endif /* __AUFS_BRANCH_H__ */
7f207e10 4871diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
fbc438ed
JR
4872--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 08:00:00.000000000 +0800
4873+++ linux/fs/aufs/conf.mk 2019-07-11 21:21:54.379051070 +0800
2121bcd9
AM
4874@@ -0,0 +1,40 @@
4875+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
4876+
4877+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
4878+
4879+define AuConf
4880+ifdef ${1}
4881+AuConfStr += ${1}=${${1}}
4882+endif
4883+endef
4884+
b752ccd1 4885+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 4886+ SBILIST \
7f207e10 4887+ HNOTIFY HFSNOTIFY \
4a4d8108 4888+ EXPORT INO_T_64 \
c1595e42 4889+ XATTR \
076b876e 4890+ FHSM \
4a4d8108 4891+ RDU \
8b6a4947 4892+ DIRREN \
4a4d8108
AM
4893+ SHWH \
4894+ BR_RAMFS \
4895+ BR_FUSE POLL \
4896+ BR_HFSPLUS \
4897+ BDEV_LOOP \
b752ccd1
AM
4898+ DEBUG MAGIC_SYSRQ
4899+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
4900+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
4901+
4902+AuConfName = ${obj}/conf.str
4903+${AuConfName}.tmp: FORCE
4904+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
4905+${AuConfName}: ${AuConfName}.tmp
4906+ @diff -q $< $@ > /dev/null 2>&1 || { \
4907+ echo ' GEN ' $@; \
4908+ cp -p $< $@; \
4909+ }
4910+FORCE:
4911+clean-files += ${AuConfName} ${AuConfName}.tmp
4912+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
4913+
4914+-include ${srctree}/${src}/conf_priv.mk
7f207e10 4915diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
fbc438ed
JR
4916--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 08:00:00.000000000 +0800
4917+++ linux/fs/aufs/cpup.c 2019-07-11 21:21:54.379051070 +0800
9f237c51 4918@@ -0,0 +1,1458 @@
cd7a4cd9 4919+// SPDX-License-Identifier: GPL-2.0
1facf9fc 4920+/*
ba1aed25 4921+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 4922+ *
4923+ * This program, aufs is free software; you can redistribute it and/or modify
4924+ * it under the terms of the GNU General Public License as published by
4925+ * the Free Software Foundation; either version 2 of the License, or
4926+ * (at your option) any later version.
dece6358
AM
4927+ *
4928+ * This program is distributed in the hope that it will be useful,
4929+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4930+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4931+ * GNU General Public License for more details.
4932+ *
4933+ * You should have received a copy of the GNU General Public License
523b37e3 4934+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4935+ */
4936+
4937+/*
4938+ * copy-up functions, see wbr_policy.c for copy-down
4939+ */
4940+
4941+#include <linux/fs_stack.h>
dece6358 4942+#include <linux/mm.h>
8cdd5066 4943+#include <linux/task_work.h>
1facf9fc 4944+#include "aufs.h"
4945+
86dc4139 4946+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags)
1facf9fc 4947+{
4948+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
367653fa 4949+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT;
1facf9fc 4950+
86dc4139
AM
4951+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags));
4952+
4953+ dst->i_flags |= iflags & ~mask;
1facf9fc 4954+ if (au_test_fs_notime(dst->i_sb))
4955+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
4956+}
4957+
4958+void au_cpup_attr_timesizes(struct inode *inode)
4959+{
4960+ struct inode *h_inode;
4961+
5afbbe0d 4962+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4963+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 4964+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 4965+}
4966+
4967+void au_cpup_attr_nlink(struct inode *inode, int force)
4968+{
4969+ struct inode *h_inode;
4970+ struct super_block *sb;
5afbbe0d 4971+ aufs_bindex_t bindex, bbot;
1facf9fc 4972+
4973+ sb = inode->i_sb;
5afbbe0d 4974+ bindex = au_ibtop(inode);
1facf9fc 4975+ h_inode = au_h_iptr(inode, bindex);
4976+ if (!force
4977+ && !S_ISDIR(h_inode->i_mode)
4978+ && au_opt_test(au_mntflags(sb), PLINK)
4979+ && au_plink_test(inode))
4980+ return;
4981+
7eafdf33
AM
4982+ /*
4983+ * 0 can happen in revalidating.
38d290e6
JR
4984+ * h_inode->i_mutex may not be held here, but it is harmless since once
4985+ * i_nlink reaches 0, it will never become positive except O_TMPFILE
4986+ * case.
4987+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause
4988+ * the incorrect link count.
7eafdf33 4989+ */
92d182d2 4990+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 4991+
4992+ /*
4993+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
4994+ * it may includes whplink directory.
4995+ */
4996+ if (S_ISDIR(h_inode->i_mode)) {
5afbbe0d
AM
4997+ bbot = au_ibbot(inode);
4998+ for (bindex++; bindex <= bbot; bindex++) {
1facf9fc 4999+ h_inode = au_h_iptr(inode, bindex);
5000+ if (h_inode)
5001+ au_add_nlink(inode, h_inode);
5002+ }
5003+ }
5004+}
5005+
5006+void au_cpup_attr_changeable(struct inode *inode)
5007+{
5008+ struct inode *h_inode;
5009+
5afbbe0d 5010+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 5011+ inode->i_mode = h_inode->i_mode;
5012+ inode->i_uid = h_inode->i_uid;
5013+ inode->i_gid = h_inode->i_gid;
5014+ au_cpup_attr_timesizes(inode);
86dc4139 5015+ au_cpup_attr_flags(inode, h_inode->i_flags);
1facf9fc 5016+}
5017+
5018+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
5019+{
5020+ struct au_iinfo *iinfo = au_ii(inode);
5021+
1308ab2a 5022+ IiMustWriteLock(inode);
5023+
1facf9fc 5024+ iinfo->ii_higen = h_inode->i_generation;
5025+ iinfo->ii_hsb1 = h_inode->i_sb;
5026+}
5027+
5028+void au_cpup_attr_all(struct inode *inode, int force)
5029+{
5030+ struct inode *h_inode;
5031+
5afbbe0d 5032+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 5033+ au_cpup_attr_changeable(inode);
5034+ if (inode->i_nlink > 0)
5035+ au_cpup_attr_nlink(inode, force);
5036+ inode->i_rdev = h_inode->i_rdev;
5037+ inode->i_blkbits = h_inode->i_blkbits;
5038+ au_cpup_igen(inode, h_inode);
5039+}
5040+
5041+/* ---------------------------------------------------------------------- */
5042+
5043+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
5044+
5045+/* keep the timestamps of the parent dir when cpup */
5046+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
5047+ struct path *h_path)
5048+{
5049+ struct inode *h_inode;
5050+
5051+ dt->dt_dentry = dentry;
5052+ dt->dt_h_path = *h_path;
5527c038 5053+ h_inode = d_inode(h_path->dentry);
1facf9fc 5054+ dt->dt_atime = h_inode->i_atime;
5055+ dt->dt_mtime = h_inode->i_mtime;
5056+ /* smp_mb(); */
5057+}
5058+
5059+void au_dtime_revert(struct au_dtime *dt)
5060+{
5061+ struct iattr attr;
5062+ int err;
5063+
5064+ attr.ia_atime = dt->dt_atime;
5065+ attr.ia_mtime = dt->dt_mtime;
5066+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
5067+ | ATTR_ATIME | ATTR_ATIME_SET;
5068+
523b37e3
AM
5069+ /* no delegation since this is a directory */
5070+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL);
1facf9fc 5071+ if (unlikely(err))
0c3ec466 5072+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 5073+}
5074+
5075+/* ---------------------------------------------------------------------- */
5076+
86dc4139
AM
5077+/* internal use only */
5078+struct au_cpup_reg_attr {
5079+ int valid;
5080+ struct kstat st;
5081+ unsigned int iflags; /* inode->i_flags */
5082+};
5083+
1facf9fc 5084+static noinline_for_stack
86dc4139
AM
5085+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
5086+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5087+{
c1595e42 5088+ int err, sbits, icex;
7e9cd9fe
AM
5089+ unsigned int mnt_flags;
5090+ unsigned char verbose;
1facf9fc 5091+ struct iattr ia;
5092+ struct path h_path;
1308ab2a 5093+ struct inode *h_isrc, *h_idst;
86dc4139 5094+ struct kstat *h_st;
c1595e42 5095+ struct au_branch *br;
1facf9fc 5096+
5097+ h_path.dentry = au_h_dptr(dst, bindex);
5527c038 5098+ h_idst = d_inode(h_path.dentry);
c1595e42
JR
5099+ br = au_sbr(dst->d_sb, bindex);
5100+ h_path.mnt = au_br_mnt(br);
5527c038 5101+ h_isrc = d_inode(h_src);
1308ab2a 5102+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 5103+ | ATTR_ATIME | ATTR_MTIME
5104+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
86dc4139
AM
5105+ if (h_src_attr && h_src_attr->valid) {
5106+ h_st = &h_src_attr->st;
5107+ ia.ia_uid = h_st->uid;
5108+ ia.ia_gid = h_st->gid;
5109+ ia.ia_atime = h_st->atime;
5110+ ia.ia_mtime = h_st->mtime;
5111+ if (h_idst->i_mode != h_st->mode
5112+ && !S_ISLNK(h_idst->i_mode)) {
5113+ ia.ia_valid |= ATTR_MODE;
5114+ ia.ia_mode = h_st->mode;
5115+ }
5116+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID));
5117+ au_cpup_attr_flags(h_idst, h_src_attr->iflags);
5118+ } else {
5119+ ia.ia_uid = h_isrc->i_uid;
5120+ ia.ia_gid = h_isrc->i_gid;
5121+ ia.ia_atime = h_isrc->i_atime;
5122+ ia.ia_mtime = h_isrc->i_mtime;
5123+ if (h_idst->i_mode != h_isrc->i_mode
5124+ && !S_ISLNK(h_idst->i_mode)) {
5125+ ia.ia_valid |= ATTR_MODE;
5126+ ia.ia_mode = h_isrc->i_mode;
5127+ }
5128+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
5129+ au_cpup_attr_flags(h_idst, h_isrc->i_flags);
1308ab2a 5130+ }
523b37e3
AM
5131+ /* no delegation since it is just created */
5132+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 5133+
5134+ /* is this nfs only? */
5135+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
5136+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
5137+ ia.ia_mode = h_isrc->i_mode;
523b37e3 5138+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 5139+ }
5140+
c1595e42 5141+ icex = br->br_perm & AuBrAttr_ICEX;
7e9cd9fe
AM
5142+ if (!err) {
5143+ mnt_flags = au_mntflags(dst->d_sb);
5144+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
5145+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose);
5146+ }
c1595e42 5147+
1facf9fc 5148+ return err;
5149+}
5150+
5151+/* ---------------------------------------------------------------------- */
5152+
5153+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
5154+ char *buf, unsigned long blksize)
5155+{
5156+ int err;
5157+ size_t sz, rbytes, wbytes;
5158+ unsigned char all_zero;
5159+ char *p, *zp;
febd17d6 5160+ struct inode *h_inode;
1facf9fc 5161+ /* reduce stack usage */
5162+ struct iattr *ia;
5163+
5164+ zp = page_address(ZERO_PAGE(0));
5165+ if (unlikely(!zp))
5166+ return -ENOMEM; /* possible? */
5167+
5168+ err = 0;
5169+ all_zero = 0;
5170+ while (len) {
5171+ AuDbg("len %lld\n", len);
5172+ sz = blksize;
5173+ if (len < blksize)
5174+ sz = len;
5175+
5176+ rbytes = 0;
5177+ /* todo: signal_pending? */
5178+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
5179+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
5180+ err = rbytes;
5181+ }
5182+ if (unlikely(err < 0))
5183+ break;
5184+
5185+ all_zero = 0;
5186+ if (len >= rbytes && rbytes == blksize)
5187+ all_zero = !memcmp(buf, zp, rbytes);
5188+ if (!all_zero) {
5189+ wbytes = rbytes;
5190+ p = buf;
5191+ while (wbytes) {
5192+ size_t b;
5193+
5194+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
5195+ err = b;
5196+ /* todo: signal_pending? */
5197+ if (unlikely(err == -EAGAIN || err == -EINTR))
5198+ continue;
5199+ if (unlikely(err < 0))
5200+ break;
5201+ wbytes -= b;
5202+ p += b;
5203+ }
392086de
AM
5204+ if (unlikely(err < 0))
5205+ break;
1facf9fc 5206+ } else {
5207+ loff_t res;
5208+
5209+ AuLabel(hole);
5210+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
5211+ err = res;
5212+ if (unlikely(res < 0))
5213+ break;
5214+ }
5215+ len -= rbytes;
5216+ err = 0;
5217+ }
5218+
5219+ /* the last block may be a hole */
5220+ if (!err && all_zero) {
5221+ AuLabel(last hole);
5222+
5223+ err = 1;
2000de60 5224+ if (au_test_nfs(dst->f_path.dentry->d_sb)) {
1facf9fc 5225+ /* nfs requires this step to make last hole */
5226+ /* is this only nfs? */
5227+ do {
5228+ /* todo: signal_pending? */
5229+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
5230+ } while (err == -EAGAIN || err == -EINTR);
5231+ if (err == 1)
5232+ dst->f_pos--;
5233+ }
5234+
5235+ if (err == 1) {
5236+ ia = (void *)buf;
5237+ ia->ia_size = dst->f_pos;
5238+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
5239+ ia->ia_file = dst;
febd17d6
JR
5240+ h_inode = file_inode(dst);
5241+ inode_lock_nested(h_inode, AuLsc_I_CHILD2);
523b37e3
AM
5242+ /* no delegation since it is just created */
5243+ err = vfsub_notify_change(&dst->f_path, ia,
5244+ /*delegated*/NULL);
febd17d6 5245+ inode_unlock(h_inode);
1facf9fc 5246+ }
5247+ }
5248+
5249+ return err;
5250+}
5251+
5252+int au_copy_file(struct file *dst, struct file *src, loff_t len)
5253+{
5254+ int err;
5255+ unsigned long blksize;
5256+ unsigned char do_kfree;
5257+ char *buf;
9f237c51 5258+ struct super_block *h_sb;
1facf9fc 5259+
5260+ err = -ENOMEM;
9f237c51
AM
5261+ h_sb = file_inode(dst)->i_sb;
5262+ blksize = h_sb->s_blocksize;
1facf9fc 5263+ if (!blksize || PAGE_SIZE < blksize)
5264+ blksize = PAGE_SIZE;
5265+ AuDbg("blksize %lu\n", blksize);
5266+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
5267+ if (do_kfree)
5268+ buf = kmalloc(blksize, GFP_NOFS);
5269+ else
5270+ buf = (void *)__get_free_page(GFP_NOFS);
5271+ if (unlikely(!buf))
5272+ goto out;
5273+
5274+ if (len > (1 << 22))
5275+ AuDbg("copying a large file %lld\n", (long long)len);
5276+
5277+ src->f_pos = 0;
5278+ dst->f_pos = 0;
5279+ err = au_do_copy_file(dst, src, len, buf, blksize);
9f237c51
AM
5280+ if (do_kfree) {
5281+ AuDebugOn(!au_kfree_do_sz_test(blksize));
5282+ au_kfree_do_rcu(buf);
5283+ } else
1c60b727 5284+ free_page((unsigned long)buf);
1facf9fc 5285+
4f0767ce 5286+out:
1facf9fc 5287+ return err;
5288+}
5289+
1c60b727
AM
5290+static int au_do_copy(struct file *dst, struct file *src, loff_t len)
5291+{
5292+ int err;
5293+ struct super_block *h_src_sb;
5294+ struct inode *h_src_inode;
5295+
5296+ h_src_inode = file_inode(src);
5297+ h_src_sb = h_src_inode->i_sb;
5298+
5299+ /* XFS acquires inode_lock */
5300+ if (!au_test_xfs(h_src_sb))
5301+ err = au_copy_file(dst, src, len);
5302+ else {
3c1bdaff 5303+ inode_unlock_shared(h_src_inode);
1c60b727 5304+ err = au_copy_file(dst, src, len);
be118d29 5305+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727
AM
5306+ }
5307+
5308+ return err;
5309+}
5310+
5311+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len)
5312+{
5313+ int err;
9f237c51 5314+ loff_t lo;
1c60b727
AM
5315+ struct super_block *h_src_sb;
5316+ struct inode *h_src_inode;
5317+
5318+ h_src_inode = file_inode(src);
5319+ h_src_sb = h_src_inode->i_sb;
5320+ if (h_src_sb != file_inode(dst)->i_sb
9f237c51 5321+ || !dst->f_op->remap_file_range) {
1c60b727
AM
5322+ err = au_do_copy(dst, src, len);
5323+ goto out;
5324+ }
5325+
5326+ if (!au_test_nfs(h_src_sb)) {
3c1bdaff 5327+ inode_unlock_shared(h_src_inode);
9f237c51 5328+ lo = vfsub_clone_file_range(src, dst, len);
be118d29 5329+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727 5330+ } else
9f237c51
AM
5331+ lo = vfsub_clone_file_range(src, dst, len);
5332+ if (lo == len) {
5333+ err = 0;
5334+ goto out; /* success */
5335+ } else if (lo >= 0)
5336+ /* todo: possible? */
5337+ /* paritially succeeded */
5338+ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len);
5339+ else if (lo != -EOPNOTSUPP) {
5340+ /* older XFS has a condition in cloning */
5341+ err = lo;
1c60b727 5342+ goto out;
9f237c51 5343+ }
1c60b727
AM
5344+
5345+ /* the backend fs on NFS may not support cloning */
5346+ err = au_do_copy(dst, src, len);
5347+
5348+out:
5349+ AuTraceErr(err);
5350+ return err;
5351+}
5352+
1facf9fc 5353+/*
5354+ * to support a sparse file which is opened with O_APPEND,
5355+ * we need to close the file.
5356+ */
c2b27bf2 5357+static int au_cp_regular(struct au_cp_generic *cpg)
1facf9fc 5358+{
5359+ int err, i;
5360+ enum { SRC, DST };
5361+ struct {
5362+ aufs_bindex_t bindex;
5363+ unsigned int flags;
5364+ struct dentry *dentry;
392086de 5365+ int force_wr;
1facf9fc 5366+ struct file *file;
1facf9fc 5367+ } *f, file[] = {
5368+ {
c2b27bf2 5369+ .bindex = cpg->bsrc,
1facf9fc 5370+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
1facf9fc 5371+ },
5372+ {
c2b27bf2 5373+ .bindex = cpg->bdst,
1facf9fc 5374+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
392086de 5375+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST),
1facf9fc 5376+ }
5377+ };
acd2b654 5378+ struct au_branch *br;
521ced18 5379+ struct super_block *sb, *h_src_sb;
e2f27e51 5380+ struct inode *h_src_inode;
8cdd5066 5381+ struct task_struct *tsk = current;
1facf9fc 5382+
5383+ /* bsrc branch can be ro/rw. */
c2b27bf2 5384+ sb = cpg->dentry->d_sb;
1facf9fc 5385+ f = file;
5386+ for (i = 0; i < 2; i++, f++) {
c2b27bf2
AM
5387+ f->dentry = au_h_dptr(cpg->dentry, f->bindex);
5388+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags,
392086de 5389+ /*file*/NULL, f->force_wr);
9f237c51
AM
5390+ if (IS_ERR(f->file)) {
5391+ err = PTR_ERR(f->file);
5392+ if (i == SRC)
5393+ goto out;
5394+ else
5395+ goto out_src;
5396+ }
1facf9fc 5397+ }
5398+
5399+ /* try stopping to update while we copyup */
e2f27e51 5400+ h_src_inode = d_inode(file[SRC].dentry);
521ced18
JR
5401+ h_src_sb = h_src_inode->i_sb;
5402+ if (!au_test_nfs(h_src_sb))
e2f27e51 5403+ IMustLock(h_src_inode);
1c60b727 5404+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len);
1facf9fc 5405+
8cdd5066
JR
5406+ /* i wonder if we had O_NO_DELAY_FPUT flag */
5407+ if (tsk->flags & PF_KTHREAD)
5408+ __fput_sync(file[DST].file);
5409+ else {
062440b3 5410+ /* it happened actually */
8cdd5066
JR
5411+ fput(file[DST].file);
5412+ /*
5413+ * too bad.
5414+ * we have to call both since we don't know which place the file
5415+ * was added to.
5416+ */
5417+ task_work_run();
5418+ flush_delayed_fput();
5419+ }
acd2b654
AM
5420+ br = au_sbr(sb, file[DST].bindex);
5421+ au_lcnt_dec(&br->br_nfiles);
523b37e3 5422+
4f0767ce 5423+out_src:
1facf9fc 5424+ fput(file[SRC].file);
acd2b654
AM
5425+ br = au_sbr(sb, file[SRC].bindex);
5426+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 5427+out:
1facf9fc 5428+ return err;
5429+}
5430+
c2b27bf2 5431+static int au_do_cpup_regular(struct au_cp_generic *cpg,
86dc4139 5432+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5433+{
5434+ int err, rerr;
5435+ loff_t l;
86dc4139 5436+ struct path h_path;
38d290e6 5437+ struct inode *h_src_inode, *h_dst_inode;
1facf9fc 5438+
5439+ err = 0;
5527c038 5440+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc);
86dc4139 5441+ l = i_size_read(h_src_inode);
c2b27bf2
AM
5442+ if (cpg->len == -1 || l < cpg->len)
5443+ cpg->len = l;
5444+ if (cpg->len) {
86dc4139 5445+ /* try stopping to update while we are referencing */
be118d29 5446+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
c2b27bf2 5447+ au_pin_hdir_unlock(cpg->pin);
1facf9fc 5448+
c2b27bf2
AM
5449+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5450+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc);
86dc4139 5451+ h_src_attr->iflags = h_src_inode->i_flags;
5527c038 5452+ if (!au_test_nfs(h_src_inode->i_sb))
521ced18 5453+ err = vfsub_getattr(&h_path, &h_src_attr->st);
5527c038 5454+ else {
3c1bdaff 5455+ inode_unlock_shared(h_src_inode);
521ced18 5456+ err = vfsub_getattr(&h_path, &h_src_attr->st);
be118d29 5457+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
5527c038 5458+ }
86dc4139 5459+ if (unlikely(err)) {
3c1bdaff 5460+ inode_unlock_shared(h_src_inode);
86dc4139
AM
5461+ goto out;
5462+ }
5463+ h_src_attr->valid = 1;
e2f27e51
AM
5464+ if (!au_test_nfs(h_src_inode->i_sb)) {
5465+ err = au_cp_regular(cpg);
3c1bdaff 5466+ inode_unlock_shared(h_src_inode);
e2f27e51 5467+ } else {
3c1bdaff 5468+ inode_unlock_shared(h_src_inode);
e2f27e51
AM
5469+ err = au_cp_regular(cpg);
5470+ }
c2b27bf2 5471+ rerr = au_pin_hdir_relock(cpg->pin);
86dc4139
AM
5472+ if (!err && rerr)
5473+ err = rerr;
1facf9fc 5474+ }
38d290e6
JR
5475+ if (!err && (h_src_inode->i_state & I_LINKABLE)) {
5476+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst);
5527c038 5477+ h_dst_inode = d_inode(h_path.dentry);
38d290e6
JR
5478+ spin_lock(&h_dst_inode->i_lock);
5479+ h_dst_inode->i_state |= I_LINKABLE;
5480+ spin_unlock(&h_dst_inode->i_lock);
5481+ }
1facf9fc 5482+
4f0767ce 5483+out:
1facf9fc 5484+ return err;
5485+}
5486+
5487+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
5488+ struct inode *h_dir)
5489+{
5490+ int err, symlen;
5491+ mm_segment_t old_fs;
b752ccd1
AM
5492+ union {
5493+ char *k;
5494+ char __user *u;
5495+ } sym;
1facf9fc 5496+
5497+ err = -ENOMEM;
537831f9 5498+ sym.k = (void *)__get_free_page(GFP_NOFS);
b752ccd1 5499+ if (unlikely(!sym.k))
1facf9fc 5500+ goto out;
5501+
9dbd164d 5502+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
1facf9fc 5503+ old_fs = get_fs();
5504+ set_fs(KERNEL_DS);
a2654f78 5505+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX);
1facf9fc 5506+ err = symlen;
5507+ set_fs(old_fs);
5508+
5509+ if (symlen > 0) {
b752ccd1
AM
5510+ sym.k[symlen] = 0;
5511+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 5512+ }
1c60b727 5513+ free_page((unsigned long)sym.k);
1facf9fc 5514+
4f0767ce 5515+out:
1facf9fc 5516+ return err;
5517+}
5518+
8cdd5066
JR
5519+/*
5520+ * regardless 'acl' option, reset all ACL.
5521+ * All ACL will be copied up later from the original entry on the lower branch.
5522+ */
5523+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode)
5524+{
5525+ int err;
5526+ struct dentry *h_dentry;
5527+ struct inode *h_inode;
5528+
5529+ h_dentry = h_path->dentry;
5530+ h_inode = d_inode(h_dentry);
5531+ /* forget_all_cached_acls(h_inode)); */
5532+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS);
5533+ AuTraceErr(err);
5534+ if (err == -EOPNOTSUPP)
5535+ err = 0;
5536+ if (!err)
5537+ err = vfsub_acl_chmod(h_inode, mode);
5538+
5539+ AuTraceErr(err);
5540+ return err;
5541+}
5542+
5543+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent,
5544+ struct inode *h_dir, struct path *h_path)
5545+{
5546+ int err;
5547+ struct inode *dir, *inode;
5548+
5549+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT);
5550+ AuTraceErr(err);
5551+ if (err == -EOPNOTSUPP)
5552+ err = 0;
5553+ if (unlikely(err))
5554+ goto out;
5555+
5556+ /*
5557+ * strange behaviour from the users view,
acd2b654 5558+ * particularly setattr case
8cdd5066
JR
5559+ */
5560+ dir = d_inode(dst_parent);
5afbbe0d 5561+ if (au_ibtop(dir) == cpg->bdst)
8cdd5066
JR
5562+ au_cpup_attr_nlink(dir, /*force*/1);
5563+ inode = d_inode(cpg->dentry);
5564+ au_cpup_attr_nlink(inode, /*force*/1);
5565+
5566+out:
5567+ return err;
5568+}
5569+
1facf9fc 5570+static noinline_for_stack
c2b27bf2 5571+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent,
86dc4139 5572+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5573+{
5574+ int err;
5575+ umode_t mode;
5576+ unsigned int mnt_flags;
076b876e 5577+ unsigned char isdir, isreg, force;
c2b27bf2 5578+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5579+ struct au_dtime dt;
5580+ struct path h_path;
5581+ struct dentry *h_src, *h_dst, *h_parent;
8cdd5066 5582+ struct inode *h_inode, *h_dir;
1facf9fc 5583+ struct super_block *sb;
5584+
5585+ /* bsrc branch can be ro/rw. */
c2b27bf2 5586+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038
JR
5587+ h_inode = d_inode(h_src);
5588+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc));
1facf9fc 5589+
5590+ /* try stopping to be referenced while we are creating */
c2b27bf2
AM
5591+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
5592+ if (au_ftest_cpup(cpg->flags, RENAME))
86dc4139
AM
5593+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX,
5594+ AUFS_WH_PFX_LEN));
1facf9fc 5595+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5596+ h_dir = d_inode(h_parent);
1facf9fc 5597+ IMustLock(h_dir);
5598+ AuDebugOn(h_parent != h_dst->d_parent);
5599+
c2b27bf2
AM
5600+ sb = cpg->dentry->d_sb;
5601+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst);
1facf9fc 5602+ if (do_dt) {
5603+ h_path.dentry = h_parent;
5604+ au_dtime_store(&dt, dst_parent, &h_path);
5605+ }
5606+ h_path.dentry = h_dst;
5607+
076b876e 5608+ isreg = 0;
1facf9fc 5609+ isdir = 0;
5610+ mode = h_inode->i_mode;
5611+ switch (mode & S_IFMT) {
5612+ case S_IFREG:
076b876e 5613+ isreg = 1;
cd7a4cd9 5614+ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true);
1facf9fc 5615+ if (!err)
c2b27bf2 5616+ err = au_do_cpup_regular(cpg, h_src_attr);
1facf9fc 5617+ break;
5618+ case S_IFDIR:
5619+ isdir = 1;
5620+ err = vfsub_mkdir(h_dir, &h_path, mode);
8cdd5066
JR
5621+ if (!err)
5622+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path);
1facf9fc 5623+ break;
5624+ case S_IFLNK:
5625+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
5626+ break;
5627+ case S_IFCHR:
5628+ case S_IFBLK:
5629+ AuDebugOn(!capable(CAP_MKNOD));
5630+ /*FALLTHROUGH*/
5631+ case S_IFIFO:
5632+ case S_IFSOCK:
5633+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
5634+ break;
5635+ default:
5636+ AuIOErr("Unknown inode type 0%o\n", mode);
5637+ err = -EIO;
5638+ }
8cdd5066
JR
5639+ if (!err)
5640+ err = au_reset_acl(h_dir, &h_path, mode);
1facf9fc 5641+
5642+ mnt_flags = au_mntflags(sb);
5643+ if (!au_opt_test(mnt_flags, UDBA_NONE)
5644+ && !isdir
5645+ && au_opt_test(mnt_flags, XINO)
38d290e6
JR
5646+ && (h_inode->i_nlink == 1
5647+ || (h_inode->i_state & I_LINKABLE))
1facf9fc 5648+ /* todo: unnecessary? */
5527c038 5649+ /* && d_inode(cpg->dentry)->i_nlink == 1 */
c2b27bf2
AM
5650+ && cpg->bdst < cpg->bsrc
5651+ && !au_ftest_cpup(cpg->flags, KEEPLINO))
5652+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 5653+ /* ignore this error */
5654+
076b876e
AM
5655+ if (!err) {
5656+ force = 0;
5657+ if (isreg) {
5658+ force = !!cpg->len;
5659+ if (cpg->len == -1)
5660+ force = !!i_size_read(h_inode);
5661+ }
5662+ au_fhsm_wrote(sb, cpg->bdst, force);
5663+ }
5664+
1facf9fc 5665+ if (do_dt)
5666+ au_dtime_revert(&dt);
5667+ return err;
5668+}
5669+
392086de 5670+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path)
86dc4139
AM
5671+{
5672+ int err;
392086de 5673+ struct dentry *dentry, *h_dentry, *h_parent, *parent;
86dc4139 5674+ struct inode *h_dir;
392086de 5675+ aufs_bindex_t bdst;
86dc4139 5676+
392086de
AM
5677+ dentry = cpg->dentry;
5678+ bdst = cpg->bdst;
5679+ h_dentry = au_h_dptr(dentry, bdst);
5680+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) {
5681+ dget(h_dentry);
5682+ au_set_h_dptr(dentry, bdst, NULL);
5683+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
5684+ if (!err)
5685+ h_path->dentry = dget(au_h_dptr(dentry, bdst));
86dc4139 5686+ au_set_h_dptr(dentry, bdst, h_dentry);
392086de
AM
5687+ } else {
5688+ err = 0;
5689+ parent = dget_parent(dentry);
5690+ h_parent = au_h_dptr(parent, bdst);
5691+ dput(parent);
5692+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
5693+ if (IS_ERR(h_path->dentry))
5694+ err = PTR_ERR(h_path->dentry);
86dc4139 5695+ }
392086de
AM
5696+ if (unlikely(err))
5697+ goto out;
86dc4139 5698+
86dc4139 5699+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 5700+ h_dir = d_inode(h_parent);
86dc4139 5701+ IMustLock(h_dir);
523b37e3
AM
5702+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry);
5703+ /* no delegation since it is just created */
f2c43d5f
AM
5704+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL,
5705+ /*flags*/0);
86dc4139
AM
5706+ dput(h_path->dentry);
5707+
5708+out:
5709+ return err;
5710+}
5711+
1facf9fc 5712+/*
5713+ * copyup the @dentry from @bsrc to @bdst.
5714+ * the caller must set the both of lower dentries.
5715+ * @len is for truncating when it is -1 copyup the entire file.
5716+ * in link/rename cases, @dst_parent may be different from the real one.
c2b27bf2 5717+ * basic->bsrc can be larger than basic->bdst.
f2c43d5f 5718+ * aufs doesn't touch the credential so
acd2b654 5719+ * security_inode_copy_up{,_xattr}() are unnecessary.
1facf9fc 5720+ */
c2b27bf2 5721+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5722+{
5723+ int err, rerr;
5afbbe0d 5724+ aufs_bindex_t old_ibtop;
1facf9fc 5725+ unsigned char isdir, plink;
1facf9fc 5726+ struct dentry *h_src, *h_dst, *h_parent;
5527c038 5727+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode;
1facf9fc 5728+ struct super_block *sb;
86dc4139 5729+ struct au_branch *br;
acd2b654 5730+ /* to reduce stack size */
c2b27bf2
AM
5731+ struct {
5732+ struct au_dtime dt;
5733+ struct path h_path;
5734+ struct au_cpup_reg_attr h_src_attr;
5735+ } *a;
1facf9fc 5736+
c2b27bf2
AM
5737+ err = -ENOMEM;
5738+ a = kmalloc(sizeof(*a), GFP_NOFS);
5739+ if (unlikely(!a))
5740+ goto out;
5741+ a->h_src_attr.valid = 0;
1facf9fc 5742+
c2b27bf2
AM
5743+ sb = cpg->dentry->d_sb;
5744+ br = au_sbr(sb, cpg->bdst);
5745+ a->h_path.mnt = au_br_mnt(br);
5746+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
1facf9fc 5747+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5748+ h_dir = d_inode(h_parent);
1facf9fc 5749+ IMustLock(h_dir);
5750+
c2b27bf2 5751+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5752+ inode = d_inode(cpg->dentry);
1facf9fc 5753+
5754+ if (!dst_parent)
c2b27bf2 5755+ dst_parent = dget_parent(cpg->dentry);
1facf9fc 5756+ else
5757+ dget(dst_parent);
5758+
5759+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
c2b27bf2 5760+ dst_inode = au_h_iptr(inode, cpg->bdst);
1facf9fc 5761+ if (dst_inode) {
5762+ if (unlikely(!plink)) {
5763+ err = -EIO;
027c5e7a
AM
5764+ AuIOErr("hi%lu(i%lu) exists on b%d "
5765+ "but plink is disabled\n",
c2b27bf2
AM
5766+ dst_inode->i_ino, inode->i_ino, cpg->bdst);
5767+ goto out_parent;
1facf9fc 5768+ }
5769+
5770+ if (dst_inode->i_nlink) {
c2b27bf2 5771+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5772+
c2b27bf2 5773+ h_src = au_plink_lkup(inode, cpg->bdst);
1facf9fc 5774+ err = PTR_ERR(h_src);
5775+ if (IS_ERR(h_src))
c2b27bf2 5776+ goto out_parent;
5527c038 5777+ if (unlikely(d_is_negative(h_src))) {
1facf9fc 5778+ err = -EIO;
79b8bda9 5779+ AuIOErr("i%lu exists on b%d "
027c5e7a 5780+ "but not pseudo-linked\n",
79b8bda9 5781+ inode->i_ino, cpg->bdst);
1facf9fc 5782+ dput(h_src);
c2b27bf2 5783+ goto out_parent;
1facf9fc 5784+ }
5785+
5786+ if (do_dt) {
c2b27bf2
AM
5787+ a->h_path.dentry = h_parent;
5788+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
1facf9fc 5789+ }
86dc4139 5790+
c2b27bf2 5791+ a->h_path.dentry = h_dst;
523b37e3
AM
5792+ delegated = NULL;
5793+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated);
c2b27bf2 5794+ if (!err && au_ftest_cpup(cpg->flags, RENAME))
392086de 5795+ err = au_do_ren_after_cpup(cpg, &a->h_path);
1facf9fc 5796+ if (do_dt)
c2b27bf2 5797+ au_dtime_revert(&a->dt);
523b37e3
AM
5798+ if (unlikely(err == -EWOULDBLOCK)) {
5799+ pr_warn("cannot retry for NFSv4 delegation"
5800+ " for an internal link\n");
5801+ iput(delegated);
5802+ }
1facf9fc 5803+ dput(h_src);
c2b27bf2 5804+ goto out_parent;
1facf9fc 5805+ } else
5806+ /* todo: cpup_wh_file? */
5807+ /* udba work */
4a4d8108 5808+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 5809+ }
5810+
86dc4139 5811+ isdir = S_ISDIR(inode->i_mode);
5afbbe0d 5812+ old_ibtop = au_ibtop(inode);
c2b27bf2 5813+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr);
1facf9fc 5814+ if (unlikely(err))
86dc4139 5815+ goto out_rev;
5527c038 5816+ dst_inode = d_inode(h_dst);
febd17d6 5817+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2);
86dc4139 5818+ /* todo: necessary? */
c2b27bf2 5819+ /* au_pin_hdir_unlock(cpg->pin); */
1facf9fc 5820+
c2b27bf2 5821+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr);
86dc4139
AM
5822+ if (unlikely(err)) {
5823+ /* todo: necessary? */
c2b27bf2 5824+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */
febd17d6 5825+ inode_unlock(dst_inode);
86dc4139
AM
5826+ goto out_rev;
5827+ }
5828+
5afbbe0d 5829+ if (cpg->bdst < old_ibtop) {
86dc4139 5830+ if (S_ISREG(inode->i_mode)) {
c2b27bf2 5831+ err = au_dy_iaop(inode, cpg->bdst, dst_inode);
86dc4139 5832+ if (unlikely(err)) {
c2b27bf2
AM
5833+ /* ignore an error */
5834+ /* au_pin_hdir_relock(cpg->pin); */
febd17d6 5835+ inode_unlock(dst_inode);
86dc4139 5836+ goto out_rev;
4a4d8108 5837+ }
4a4d8108 5838+ }
5afbbe0d 5839+ au_set_ibtop(inode, cpg->bdst);
c2b27bf2 5840+ } else
5afbbe0d 5841+ au_set_ibbot(inode, cpg->bdst);
c2b27bf2 5842+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode),
86dc4139
AM
5843+ au_hi_flags(inode, isdir));
5844+
5845+ /* todo: necessary? */
c2b27bf2 5846+ /* err = au_pin_hdir_relock(cpg->pin); */
febd17d6 5847+ inode_unlock(dst_inode);
86dc4139
AM
5848+ if (unlikely(err))
5849+ goto out_rev;
5850+
5527c038 5851+ src_inode = d_inode(h_src);
86dc4139 5852+ if (!isdir
5527c038
JR
5853+ && (src_inode->i_nlink > 1
5854+ || src_inode->i_state & I_LINKABLE)
86dc4139 5855+ && plink)
c2b27bf2 5856+ au_plink_append(inode, cpg->bdst, h_dst);
86dc4139 5857+
c2b27bf2
AM
5858+ if (au_ftest_cpup(cpg->flags, RENAME)) {
5859+ a->h_path.dentry = h_dst;
392086de 5860+ err = au_do_ren_after_cpup(cpg, &a->h_path);
86dc4139
AM
5861+ }
5862+ if (!err)
c2b27bf2 5863+ goto out_parent; /* success */
1facf9fc 5864+
5865+ /* revert */
4a4d8108 5866+out_rev:
c2b27bf2
AM
5867+ a->h_path.dentry = h_parent;
5868+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
5869+ a->h_path.dentry = h_dst;
86dc4139 5870+ rerr = 0;
5527c038 5871+ if (d_is_positive(h_dst)) {
523b37e3
AM
5872+ if (!isdir) {
5873+ /* no delegation since it is just created */
5874+ rerr = vfsub_unlink(h_dir, &a->h_path,
5875+ /*delegated*/NULL, /*force*/0);
5876+ } else
c2b27bf2 5877+ rerr = vfsub_rmdir(h_dir, &a->h_path);
86dc4139 5878+ }
c2b27bf2 5879+ au_dtime_revert(&a->dt);
1facf9fc 5880+ if (rerr) {
5881+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
5882+ err = -EIO;
5883+ }
c2b27bf2 5884+out_parent:
1facf9fc 5885+ dput(dst_parent);
9f237c51 5886+ au_kfree_rcu(a);
c2b27bf2 5887+out:
1facf9fc 5888+ return err;
5889+}
5890+
7e9cd9fe 5891+#if 0 /* reserved */
1facf9fc 5892+struct au_cpup_single_args {
5893+ int *errp;
c2b27bf2 5894+ struct au_cp_generic *cpg;
1facf9fc 5895+ struct dentry *dst_parent;
5896+};
5897+
5898+static void au_call_cpup_single(void *args)
5899+{
5900+ struct au_cpup_single_args *a = args;
86dc4139 5901+
c2b27bf2
AM
5902+ au_pin_hdir_acquire_nest(a->cpg->pin);
5903+ *a->errp = au_cpup_single(a->cpg, a->dst_parent);
5904+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5905+}
c2b27bf2 5906+#endif
1facf9fc 5907+
53392da6
AM
5908+/*
5909+ * prevent SIGXFSZ in copy-up.
5910+ * testing CAP_MKNOD is for generic fs,
5911+ * but CAP_FSETID is for xfs only, currently.
5912+ */
86dc4139 5913+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode)
53392da6
AM
5914+{
5915+ int do_sio;
86dc4139
AM
5916+ struct super_block *sb;
5917+ struct inode *h_dir;
53392da6
AM
5918+
5919+ do_sio = 0;
86dc4139 5920+ sb = au_pinned_parent(pin)->d_sb;
53392da6
AM
5921+ if (!au_wkq_test()
5922+ && (!au_sbi(sb)->si_plink_maint_pid
5923+ || au_plink_maint(sb, AuLock_NOPLM))) {
5924+ switch (mode & S_IFMT) {
5925+ case S_IFREG:
5926+ /* no condition about RLIMIT_FSIZE and the file size */
5927+ do_sio = 1;
5928+ break;
5929+ case S_IFCHR:
5930+ case S_IFBLK:
5931+ do_sio = !capable(CAP_MKNOD);
5932+ break;
5933+ }
5934+ if (!do_sio)
5935+ do_sio = ((mode & (S_ISUID | S_ISGID))
5936+ && !capable(CAP_FSETID));
86dc4139
AM
5937+ /* this workaround may be removed in the future */
5938+ if (!do_sio) {
5939+ h_dir = au_pinned_h_dir(pin);
5940+ do_sio = h_dir->i_mode & S_ISVTX;
5941+ }
53392da6
AM
5942+ }
5943+
5944+ return do_sio;
5945+}
5946+
7e9cd9fe 5947+#if 0 /* reserved */
c2b27bf2 5948+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5949+{
5950+ int err, wkq_err;
1facf9fc 5951+ struct dentry *h_dentry;
5952+
c2b27bf2 5953+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5954+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode))
c2b27bf2 5955+ err = au_cpup_single(cpg, dst_parent);
1facf9fc 5956+ else {
5957+ struct au_cpup_single_args args = {
5958+ .errp = &err,
c2b27bf2
AM
5959+ .cpg = cpg,
5960+ .dst_parent = dst_parent
1facf9fc 5961+ };
5962+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
5963+ if (unlikely(wkq_err))
5964+ err = wkq_err;
5965+ }
5966+
5967+ return err;
5968+}
c2b27bf2 5969+#endif
1facf9fc 5970+
5971+/*
5972+ * copyup the @dentry from the first active lower branch to @bdst,
5973+ * using au_cpup_single().
5974+ */
c2b27bf2 5975+static int au_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5976+{
5977+ int err;
c2b27bf2
AM
5978+ unsigned int flags_orig;
5979+ struct dentry *dentry;
5980+
5981+ AuDebugOn(cpg->bsrc < 0);
1facf9fc 5982+
c2b27bf2 5983+ dentry = cpg->dentry;
86dc4139 5984+ DiMustWriteLock(dentry);
1facf9fc 5985+
c2b27bf2 5986+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1);
1facf9fc 5987+ if (!err) {
c2b27bf2
AM
5988+ flags_orig = cpg->flags;
5989+ au_fset_cpup(cpg->flags, RENAME);
5990+ err = au_cpup_single(cpg, NULL);
5991+ cpg->flags = flags_orig;
1facf9fc 5992+ if (!err)
5993+ return 0; /* success */
5994+
5995+ /* revert */
c2b27bf2 5996+ au_set_h_dptr(dentry, cpg->bdst, NULL);
5afbbe0d 5997+ au_set_dbtop(dentry, cpg->bsrc);
1facf9fc 5998+ }
5999+
6000+ return err;
6001+}
6002+
6003+struct au_cpup_simple_args {
6004+ int *errp;
c2b27bf2 6005+ struct au_cp_generic *cpg;
1facf9fc 6006+};
6007+
6008+static void au_call_cpup_simple(void *args)
6009+{
6010+ struct au_cpup_simple_args *a = args;
86dc4139 6011+
c2b27bf2
AM
6012+ au_pin_hdir_acquire_nest(a->cpg->pin);
6013+ *a->errp = au_cpup_simple(a->cpg);
6014+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 6015+}
6016+
c2b27bf2 6017+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 6018+{
6019+ int err, wkq_err;
c2b27bf2
AM
6020+ struct dentry *dentry, *parent;
6021+ struct file *h_file;
1facf9fc 6022+ struct inode *h_dir;
6023+
c2b27bf2
AM
6024+ dentry = cpg->dentry;
6025+ h_file = NULL;
6026+ if (au_ftest_cpup(cpg->flags, HOPEN)) {
6027+ AuDebugOn(cpg->bsrc < 0);
392086de 6028+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0);
c2b27bf2
AM
6029+ err = PTR_ERR(h_file);
6030+ if (IS_ERR(h_file))
6031+ goto out;
6032+ }
6033+
1facf9fc 6034+ parent = dget_parent(dentry);
5527c038 6035+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
53392da6 6036+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
5527c038 6037+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 6038+ err = au_cpup_simple(cpg);
1facf9fc 6039+ else {
6040+ struct au_cpup_simple_args args = {
6041+ .errp = &err,
c2b27bf2 6042+ .cpg = cpg
1facf9fc 6043+ };
6044+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
6045+ if (unlikely(wkq_err))
6046+ err = wkq_err;
6047+ }
6048+
6049+ dput(parent);
c2b27bf2
AM
6050+ if (h_file)
6051+ au_h_open_post(dentry, cpg->bsrc, h_file);
6052+
6053+out:
1facf9fc 6054+ return err;
6055+}
6056+
c2b27bf2 6057+int au_sio_cpup_simple(struct au_cp_generic *cpg)
367653fa 6058+{
5afbbe0d 6059+ aufs_bindex_t bsrc, bbot;
c2b27bf2 6060+ struct dentry *dentry, *h_dentry;
367653fa 6061+
c2b27bf2
AM
6062+ if (cpg->bsrc < 0) {
6063+ dentry = cpg->dentry;
5afbbe0d
AM
6064+ bbot = au_dbbot(dentry);
6065+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) {
c2b27bf2
AM
6066+ h_dentry = au_h_dptr(dentry, bsrc);
6067+ if (h_dentry) {
5527c038 6068+ AuDebugOn(d_is_negative(h_dentry));
c2b27bf2
AM
6069+ break;
6070+ }
6071+ }
5afbbe0d 6072+ AuDebugOn(bsrc > bbot);
c2b27bf2 6073+ cpg->bsrc = bsrc;
367653fa 6074+ }
c2b27bf2
AM
6075+ AuDebugOn(cpg->bsrc <= cpg->bdst);
6076+ return au_do_sio_cpup_simple(cpg);
6077+}
367653fa 6078+
c2b27bf2
AM
6079+int au_sio_cpdown_simple(struct au_cp_generic *cpg)
6080+{
6081+ AuDebugOn(cpg->bdst <= cpg->bsrc);
6082+ return au_do_sio_cpup_simple(cpg);
367653fa
AM
6083+}
6084+
1facf9fc 6085+/* ---------------------------------------------------------------------- */
6086+
6087+/*
6088+ * copyup the deleted file for writing.
6089+ */
c2b27bf2
AM
6090+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry,
6091+ struct file *file)
1facf9fc 6092+{
6093+ int err;
c2b27bf2
AM
6094+ unsigned int flags_orig;
6095+ aufs_bindex_t bsrc_orig;
c2b27bf2 6096+ struct au_dinfo *dinfo;
5afbbe0d
AM
6097+ struct {
6098+ struct au_hdentry *hd;
6099+ struct dentry *h_dentry;
6100+ } hdst, hsrc;
1facf9fc 6101+
c2b27bf2 6102+ dinfo = au_di(cpg->dentry);
1308ab2a 6103+ AuRwMustWriteLock(&dinfo->di_rwsem);
6104+
c2b27bf2 6105+ bsrc_orig = cpg->bsrc;
5afbbe0d
AM
6106+ cpg->bsrc = dinfo->di_btop;
6107+ hdst.hd = au_hdentry(dinfo, cpg->bdst);
6108+ hdst.h_dentry = hdst.hd->hd_dentry;
6109+ hdst.hd->hd_dentry = wh_dentry;
6110+ dinfo->di_btop = cpg->bdst;
6111+
6112+ hsrc.h_dentry = NULL;
027c5e7a 6113+ if (file) {
5afbbe0d
AM
6114+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc);
6115+ hsrc.h_dentry = hsrc.hd->hd_dentry;
6116+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry;
027c5e7a 6117+ }
c2b27bf2
AM
6118+ flags_orig = cpg->flags;
6119+ cpg->flags = !AuCpup_DTIME;
6120+ err = au_cpup_single(cpg, /*h_parent*/NULL);
6121+ cpg->flags = flags_orig;
027c5e7a
AM
6122+ if (file) {
6123+ if (!err)
6124+ err = au_reopen_nondir(file);
5afbbe0d 6125+ hsrc.hd->hd_dentry = hsrc.h_dentry;
1facf9fc 6126+ }
5afbbe0d
AM
6127+ hdst.hd->hd_dentry = hdst.h_dentry;
6128+ dinfo->di_btop = cpg->bsrc;
c2b27bf2 6129+ cpg->bsrc = bsrc_orig;
1facf9fc 6130+
6131+ return err;
6132+}
6133+
c2b27bf2 6134+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6135+{
6136+ int err;
c2b27bf2 6137+ aufs_bindex_t bdst;
1facf9fc 6138+ struct au_dtime dt;
c2b27bf2 6139+ struct dentry *dentry, *parent, *h_parent, *wh_dentry;
1facf9fc 6140+ struct au_branch *br;
6141+ struct path h_path;
6142+
c2b27bf2
AM
6143+ dentry = cpg->dentry;
6144+ bdst = cpg->bdst;
1facf9fc 6145+ br = au_sbr(dentry->d_sb, bdst);
6146+ parent = dget_parent(dentry);
6147+ h_parent = au_h_dptr(parent, bdst);
6148+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
6149+ err = PTR_ERR(wh_dentry);
6150+ if (IS_ERR(wh_dentry))
6151+ goto out;
6152+
6153+ h_path.dentry = h_parent;
86dc4139 6154+ h_path.mnt = au_br_mnt(br);
1facf9fc 6155+ au_dtime_store(&dt, parent, &h_path);
c2b27bf2 6156+ err = au_do_cpup_wh(cpg, wh_dentry, file);
1facf9fc 6157+ if (unlikely(err))
6158+ goto out_wh;
6159+
6160+ dget(wh_dentry);
6161+ h_path.dentry = wh_dentry;
2000de60 6162+ if (!d_is_dir(wh_dentry)) {
523b37e3 6163+ /* no delegation since it is just created */
5527c038 6164+ err = vfsub_unlink(d_inode(h_parent), &h_path,
523b37e3
AM
6165+ /*delegated*/NULL, /*force*/0);
6166+ } else
5527c038 6167+ err = vfsub_rmdir(d_inode(h_parent), &h_path);
1facf9fc 6168+ if (unlikely(err)) {
523b37e3
AM
6169+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n",
6170+ wh_dentry, err);
1facf9fc 6171+ err = -EIO;
6172+ }
6173+ au_dtime_revert(&dt);
5527c038 6174+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry);
1facf9fc 6175+
4f0767ce 6176+out_wh:
1facf9fc 6177+ dput(wh_dentry);
4f0767ce 6178+out:
1facf9fc 6179+ dput(parent);
6180+ return err;
6181+}
6182+
6183+struct au_cpup_wh_args {
6184+ int *errp;
c2b27bf2 6185+ struct au_cp_generic *cpg;
1facf9fc 6186+ struct file *file;
6187+};
6188+
6189+static void au_call_cpup_wh(void *args)
6190+{
6191+ struct au_cpup_wh_args *a = args;
86dc4139 6192+
c2b27bf2
AM
6193+ au_pin_hdir_acquire_nest(a->cpg->pin);
6194+ *a->errp = au_cpup_wh(a->cpg, a->file);
6195+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 6196+}
6197+
c2b27bf2 6198+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6199+{
6200+ int err, wkq_err;
c2b27bf2 6201+ aufs_bindex_t bdst;
c1595e42 6202+ struct dentry *dentry, *parent, *h_orph, *h_parent;
86dc4139 6203+ struct inode *dir, *h_dir, *h_tmpdir;
1facf9fc 6204+ struct au_wbr *wbr;
c2b27bf2 6205+ struct au_pin wh_pin, *pin_orig;
1facf9fc 6206+
c2b27bf2
AM
6207+ dentry = cpg->dentry;
6208+ bdst = cpg->bdst;
1facf9fc 6209+ parent = dget_parent(dentry);
5527c038 6210+ dir = d_inode(parent);
1facf9fc 6211+ h_orph = NULL;
6212+ h_parent = NULL;
6213+ h_dir = au_igrab(au_h_iptr(dir, bdst));
6214+ h_tmpdir = h_dir;
c2b27bf2 6215+ pin_orig = NULL;
1facf9fc 6216+ if (!h_dir->i_nlink) {
6217+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
6218+ h_orph = wbr->wbr_orph;
6219+
6220+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 6221+ au_set_h_dptr(parent, bdst, dget(h_orph));
5527c038 6222+ h_tmpdir = d_inode(h_orph);
1facf9fc 6223+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
6224+
febd17d6 6225+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3);
4a4d8108 6226+ /* todo: au_h_open_pre()? */
86dc4139 6227+
c2b27bf2 6228+ pin_orig = cpg->pin;
86dc4139 6229+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
c2b27bf2
AM
6230+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED);
6231+ cpg->pin = &wh_pin;
1facf9fc 6232+ }
6233+
53392da6 6234+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
5527c038 6235+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 6236+ err = au_cpup_wh(cpg, file);
1facf9fc 6237+ else {
6238+ struct au_cpup_wh_args args = {
6239+ .errp = &err,
c2b27bf2
AM
6240+ .cpg = cpg,
6241+ .file = file
1facf9fc 6242+ };
6243+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
6244+ if (unlikely(wkq_err))
6245+ err = wkq_err;
6246+ }
6247+
6248+ if (h_orph) {
febd17d6 6249+ inode_unlock(h_tmpdir);
4a4d8108 6250+ /* todo: au_h_open_post()? */
1facf9fc 6251+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 6252+ au_set_h_dptr(parent, bdst, h_parent);
c2b27bf2
AM
6253+ AuDebugOn(!pin_orig);
6254+ cpg->pin = pin_orig;
1facf9fc 6255+ }
6256+ iput(h_dir);
6257+ dput(parent);
6258+
6259+ return err;
6260+}
6261+
6262+/* ---------------------------------------------------------------------- */
6263+
6264+/*
6265+ * generic routine for both of copy-up and copy-down.
6266+ */
6267+/* cf. revalidate function in file.c */
6268+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6269+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6270+ struct au_pin *pin,
1facf9fc 6271+ struct dentry *h_parent, void *arg),
6272+ void *arg)
6273+{
6274+ int err;
6275+ struct au_pin pin;
5527c038 6276+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry;
1facf9fc 6277+
6278+ err = 0;
6279+ parent = dget_parent(dentry);
6280+ if (IS_ROOT(parent))
6281+ goto out;
6282+
6283+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
6284+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
6285+
6286+ /* do not use au_dpage */
6287+ real_parent = parent;
6288+ while (1) {
6289+ dput(parent);
6290+ parent = dget_parent(dentry);
6291+ h_parent = au_h_dptr(parent, bdst);
6292+ if (h_parent)
6293+ goto out; /* success */
6294+
6295+ /* find top dir which is necessary to cpup */
6296+ do {
6297+ d = parent;
6298+ dput(parent);
6299+ parent = dget_parent(d);
6300+ di_read_lock_parent3(parent, !AuLock_IR);
6301+ h_parent = au_h_dptr(parent, bdst);
6302+ di_read_unlock(parent, !AuLock_IR);
6303+ } while (!h_parent);
6304+
6305+ if (d != real_parent)
6306+ di_write_lock_child3(d);
6307+
6308+ /* somebody else might create while we were sleeping */
5527c038
JR
6309+ h_dentry = au_h_dptr(d, bdst);
6310+ if (!h_dentry || d_is_negative(h_dentry)) {
6311+ if (h_dentry)
5afbbe0d 6312+ au_update_dbtop(d);
1facf9fc 6313+
6314+ au_pin_set_dentry(&pin, d);
6315+ err = au_do_pin(&pin);
6316+ if (!err) {
86dc4139 6317+ err = cp(d, bdst, &pin, h_parent, arg);
1facf9fc 6318+ au_unpin(&pin);
6319+ }
6320+ }
6321+
6322+ if (d != real_parent)
6323+ di_write_unlock(d);
6324+ if (unlikely(err))
6325+ break;
6326+ }
6327+
4f0767ce 6328+out:
1facf9fc 6329+ dput(parent);
6330+ return err;
6331+}
6332+
6333+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6334+ struct au_pin *pin,
2000de60 6335+ struct dentry *h_parent __maybe_unused,
1facf9fc 6336+ void *arg __maybe_unused)
6337+{
c2b27bf2
AM
6338+ struct au_cp_generic cpg = {
6339+ .dentry = dentry,
6340+ .bdst = bdst,
6341+ .bsrc = -1,
6342+ .len = 0,
6343+ .pin = pin,
6344+ .flags = AuCpup_DTIME
6345+ };
6346+ return au_sio_cpup_simple(&cpg);
1facf9fc 6347+}
6348+
6349+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6350+{
6351+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
6352+}
6353+
6354+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6355+{
6356+ int err;
6357+ struct dentry *parent;
6358+ struct inode *dir;
6359+
6360+ parent = dget_parent(dentry);
5527c038 6361+ dir = d_inode(parent);
1facf9fc 6362+ err = 0;
6363+ if (au_h_iptr(dir, bdst))
6364+ goto out;
6365+
6366+ di_read_unlock(parent, AuLock_IR);
6367+ di_write_lock_parent(parent);
6368+ /* someone else might change our inode while we were sleeping */
6369+ if (!au_h_iptr(dir, bdst))
6370+ err = au_cpup_dirs(dentry, bdst);
6371+ di_downgrade_lock(parent, AuLock_IR);
6372+
4f0767ce 6373+out:
1facf9fc 6374+ dput(parent);
6375+ return err;
6376+}
7f207e10 6377diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
fbc438ed
JR
6378--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 08:00:00.000000000 +0800
6379+++ linux/fs/aufs/cpup.h 2019-07-11 21:21:54.379051070 +0800
062440b3
AM
6380@@ -0,0 +1,100 @@
6381+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 6382+/*
ba1aed25 6383+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 6384+ *
6385+ * This program, aufs is free software; you can redistribute it and/or modify
6386+ * it under the terms of the GNU General Public License as published by
6387+ * the Free Software Foundation; either version 2 of the License, or
6388+ * (at your option) any later version.
dece6358
AM
6389+ *
6390+ * This program is distributed in the hope that it will be useful,
6391+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6392+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6393+ * GNU General Public License for more details.
6394+ *
6395+ * You should have received a copy of the GNU General Public License
523b37e3 6396+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6397+ */
6398+
6399+/*
6400+ * copy-up/down functions
6401+ */
6402+
6403+#ifndef __AUFS_CPUP_H__
6404+#define __AUFS_CPUP_H__
6405+
6406+#ifdef __KERNEL__
6407+
dece6358 6408+#include <linux/path.h>
1facf9fc 6409+
dece6358
AM
6410+struct inode;
6411+struct file;
86dc4139 6412+struct au_pin;
dece6358 6413+
86dc4139 6414+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags);
1facf9fc 6415+void au_cpup_attr_timesizes(struct inode *inode);
6416+void au_cpup_attr_nlink(struct inode *inode, int force);
6417+void au_cpup_attr_changeable(struct inode *inode);
6418+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
6419+void au_cpup_attr_all(struct inode *inode, int force);
6420+
6421+/* ---------------------------------------------------------------------- */
6422+
c2b27bf2
AM
6423+struct au_cp_generic {
6424+ struct dentry *dentry;
6425+ aufs_bindex_t bdst, bsrc;
6426+ loff_t len;
6427+ struct au_pin *pin;
6428+ unsigned int flags;
6429+};
6430+
1facf9fc 6431+/* cpup flags */
392086de
AM
6432+#define AuCpup_DTIME 1 /* do dtime_store/revert */
6433+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
6434+ for link(2) */
6435+#define AuCpup_RENAME (1 << 2) /* rename after cpup */
6436+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in
6437+ cpup */
6438+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the
6439+ existing entry */
6440+#define AuCpup_RWDST (1 << 5) /* force write target even if
6441+ the branch is marked as RO */
c2b27bf2 6442+
8b6a4947
AM
6443+#ifndef CONFIG_AUFS_BR_HFSPLUS
6444+#undef AuCpup_HOPEN
6445+#define AuCpup_HOPEN 0
6446+#endif
6447+
1facf9fc 6448+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
6449+#define au_fset_cpup(flags, name) \
6450+ do { (flags) |= AuCpup_##name; } while (0)
6451+#define au_fclr_cpup(flags, name) \
6452+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 6453+
6454+int au_copy_file(struct file *dst, struct file *src, loff_t len);
c2b27bf2
AM
6455+int au_sio_cpup_simple(struct au_cp_generic *cpg);
6456+int au_sio_cpdown_simple(struct au_cp_generic *cpg);
6457+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file);
1facf9fc 6458+
6459+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6460+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6461+ struct au_pin *pin,
1facf9fc 6462+ struct dentry *h_parent, void *arg),
6463+ void *arg);
6464+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6465+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6466+
6467+/* ---------------------------------------------------------------------- */
6468+
6469+/* keep timestamps when copyup */
6470+struct au_dtime {
6471+ struct dentry *dt_dentry;
6472+ struct path dt_h_path;
cd7a4cd9 6473+ struct timespec64 dt_atime, dt_mtime;
1facf9fc 6474+};
6475+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
6476+ struct path *h_path);
6477+void au_dtime_revert(struct au_dtime *dt);
6478+
6479+#endif /* __KERNEL__ */
6480+#endif /* __AUFS_CPUP_H__ */
7f207e10 6481diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
fbc438ed
JR
6482--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 08:00:00.000000000 +0800
6483+++ linux/fs/aufs/dbgaufs.c 2019-07-11 21:21:54.379051070 +0800
9f237c51 6484@@ -0,0 +1,526 @@
cd7a4cd9 6485+// SPDX-License-Identifier: GPL-2.0
1facf9fc 6486+/*
ba1aed25 6487+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 6488+ *
6489+ * This program, aufs is free software; you can redistribute it and/or modify
6490+ * it under the terms of the GNU General Public License as published by
6491+ * the Free Software Foundation; either version 2 of the License, or
6492+ * (at your option) any later version.
dece6358
AM
6493+ *
6494+ * This program is distributed in the hope that it will be useful,
6495+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6496+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6497+ * GNU General Public License for more details.
6498+ *
6499+ * You should have received a copy of the GNU General Public License
523b37e3 6500+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6501+ */
6502+
6503+/*
6504+ * debugfs interface
6505+ */
6506+
6507+#include <linux/debugfs.h>
6508+#include "aufs.h"
6509+
6510+#ifndef CONFIG_SYSFS
6511+#error DEBUG_FS depends upon SYSFS
6512+#endif
6513+
6514+static struct dentry *dbgaufs;
cd7a4cd9 6515+static const mode_t dbgaufs_mode = 0444;
1facf9fc 6516+
6517+/* 20 is max digits length of ulong 64 */
6518+struct dbgaufs_arg {
6519+ int n;
6520+ char a[20 * 4];
6521+};
6522+
6523+/*
6524+ * common function for all XINO files
6525+ */
6526+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
6527+ struct file *file)
6528+{
9f237c51
AM
6529+ void *p;
6530+
6531+ p = file->private_data;
6532+ if (p) {
6533+ /* this is struct dbgaufs_arg */
6534+ AuDebugOn(!au_kfree_sz_test(p));
6535+ au_kfree_do_rcu(p);
6536+ }
1facf9fc 6537+ return 0;
6538+}
6539+
062440b3
AM
6540+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt,
6541+ int cnt)
1facf9fc 6542+{
6543+ int err;
6544+ struct kstat st;
6545+ struct dbgaufs_arg *p;
6546+
6547+ err = -ENOMEM;
6548+ p = kmalloc(sizeof(*p), GFP_NOFS);
6549+ if (unlikely(!p))
6550+ goto out;
6551+
6552+ err = 0;
6553+ p->n = 0;
6554+ file->private_data = p;
6555+ if (!xf)
6556+ goto out;
6557+
521ced18 6558+ err = vfsub_getattr(&xf->f_path, &st);
1facf9fc 6559+ if (!err) {
6560+ if (do_fcnt)
6561+ p->n = snprintf
062440b3
AM
6562+ (p->a, sizeof(p->a), "%d, %llux%u %lld\n",
6563+ cnt, st.blocks, st.blksize,
1facf9fc 6564+ (long long)st.size);
6565+ else
521ced18 6566+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n",
1facf9fc 6567+ st.blocks, st.blksize,
6568+ (long long)st.size);
6569+ AuDebugOn(p->n >= sizeof(p->a));
6570+ } else {
6571+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
6572+ err = 0;
6573+ }
6574+
4f0767ce 6575+out:
1facf9fc 6576+ return err;
1facf9fc 6577+}
6578+
6579+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
6580+ size_t count, loff_t *ppos)
6581+{
6582+ struct dbgaufs_arg *p;
6583+
6584+ p = file->private_data;
6585+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6586+}
6587+
6588+/* ---------------------------------------------------------------------- */
6589+
86dc4139
AM
6590+struct dbgaufs_plink_arg {
6591+ int n;
6592+ char a[];
6593+};
6594+
6595+static int dbgaufs_plink_release(struct inode *inode __maybe_unused,
6596+ struct file *file)
6597+{
1c60b727 6598+ free_page((unsigned long)file->private_data);
86dc4139
AM
6599+ return 0;
6600+}
6601+
6602+static int dbgaufs_plink_open(struct inode *inode, struct file *file)
6603+{
6604+ int err, i, limit;
6605+ unsigned long n, sum;
6606+ struct dbgaufs_plink_arg *p;
6607+ struct au_sbinfo *sbinfo;
6608+ struct super_block *sb;
8b6a4947 6609+ struct hlist_bl_head *hbl;
86dc4139
AM
6610+
6611+ err = -ENOMEM;
6612+ p = (void *)get_zeroed_page(GFP_NOFS);
6613+ if (unlikely(!p))
6614+ goto out;
6615+
6616+ err = -EFBIG;
6617+ sbinfo = inode->i_private;
6618+ sb = sbinfo->si_sb;
6619+ si_noflush_read_lock(sb);
6620+ if (au_opt_test(au_mntflags(sb), PLINK)) {
6621+ limit = PAGE_SIZE - sizeof(p->n);
6622+
6623+ /* the number of buckets */
6624+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH);
6625+ p->n += n;
6626+ limit -= n;
6627+
6628+ sum = 0;
8b6a4947
AM
6629+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH;
6630+ i++, hbl++) {
6631+ n = au_hbl_count(hbl);
86dc4139
AM
6632+ sum += n;
6633+
6634+ n = snprintf(p->a + p->n, limit, "%lu ", n);
6635+ p->n += n;
6636+ limit -= n;
6637+ if (unlikely(limit <= 0))
6638+ goto out_free;
6639+ }
6640+ p->a[p->n - 1] = '\n';
6641+
6642+ /* the sum of plinks */
6643+ n = snprintf(p->a + p->n, limit, "%lu\n", sum);
6644+ p->n += n;
6645+ limit -= n;
6646+ if (unlikely(limit <= 0))
6647+ goto out_free;
6648+ } else {
6649+#define str "1\n0\n0\n"
6650+ p->n = sizeof(str) - 1;
6651+ strcpy(p->a, str);
6652+#undef str
6653+ }
6654+ si_read_unlock(sb);
6655+
6656+ err = 0;
6657+ file->private_data = p;
6658+ goto out; /* success */
6659+
6660+out_free:
1c60b727 6661+ free_page((unsigned long)p);
86dc4139
AM
6662+out:
6663+ return err;
6664+}
6665+
6666+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf,
6667+ size_t count, loff_t *ppos)
6668+{
6669+ struct dbgaufs_plink_arg *p;
6670+
6671+ p = file->private_data;
6672+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6673+}
6674+
6675+static const struct file_operations dbgaufs_plink_fop = {
6676+ .owner = THIS_MODULE,
6677+ .open = dbgaufs_plink_open,
6678+ .release = dbgaufs_plink_release,
6679+ .read = dbgaufs_plink_read
6680+};
6681+
6682+/* ---------------------------------------------------------------------- */
6683+
1facf9fc 6684+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
6685+{
6686+ int err;
6687+ struct au_sbinfo *sbinfo;
6688+ struct super_block *sb;
6689+
6690+ sbinfo = inode->i_private;
6691+ sb = sbinfo->si_sb;
6692+ si_noflush_read_lock(sb);
062440b3 6693+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6694+ si_read_unlock(sb);
6695+ return err;
6696+}
6697+
6698+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 6699+ .owner = THIS_MODULE,
1facf9fc 6700+ .open = dbgaufs_xib_open,
6701+ .release = dbgaufs_xi_release,
6702+ .read = dbgaufs_xi_read
6703+};
6704+
6705+/* ---------------------------------------------------------------------- */
6706+
6707+#define DbgaufsXi_PREFIX "xi"
6708+
6709+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
6710+{
acd2b654 6711+ int err, idx;
1facf9fc 6712+ long l;
acd2b654
AM
6713+ aufs_bindex_t bindex;
6714+ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8];
1facf9fc 6715+ struct au_sbinfo *sbinfo;
6716+ struct super_block *sb;
acd2b654 6717+ struct au_xino *xi;
1facf9fc 6718+ struct file *xf;
6719+ struct qstr *name;
062440b3 6720+ struct au_branch *br;
1facf9fc 6721+
6722+ err = -ENOENT;
2000de60 6723+ name = &file->f_path.dentry->d_name;
1facf9fc 6724+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
6725+ || memcmp(name->name, DbgaufsXi_PREFIX,
6726+ sizeof(DbgaufsXi_PREFIX) - 1)))
6727+ goto out;
acd2b654
AM
6728+
6729+ AuDebugOn(name->len >= sizeof(a));
6730+ memcpy(a, name->name, name->len);
6731+ a[name->len] = '\0';
6732+ p = strchr(a, '-');
6733+ if (p)
6734+ *p = '\0';
6735+ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 6736+ if (unlikely(err))
6737+ goto out;
acd2b654
AM
6738+ bindex = l;
6739+ idx = 0;
6740+ if (p) {
6741+ err = kstrtol(p + 1, 10, &l);
6742+ if (unlikely(err))
6743+ goto out;
6744+ idx = l;
6745+ }
1facf9fc 6746+
acd2b654 6747+ err = -ENOENT;
1facf9fc 6748+ sbinfo = inode->i_private;
6749+ sb = sbinfo->si_sb;
6750+ si_noflush_read_lock(sb);
acd2b654
AM
6751+ if (unlikely(bindex < 0 || bindex > au_sbbot(sb)))
6752+ goto out_si;
6753+ br = au_sbr(sb, bindex);
6754+ xi = br->br_xino;
6755+ if (unlikely(idx >= xi->xi_nfile))
6756+ goto out_si;
6757+ xf = au_xino_file(xi, idx);
6758+ if (xf)
062440b3
AM
6759+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1,
6760+ au_xino_count(br));
1facf9fc 6761+
acd2b654
AM
6762+out_si:
6763+ si_read_unlock(sb);
4f0767ce 6764+out:
acd2b654 6765+ AuTraceErr(err);
1facf9fc 6766+ return err;
6767+}
6768+
6769+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 6770+ .owner = THIS_MODULE,
1facf9fc 6771+ .open = dbgaufs_xino_open,
6772+ .release = dbgaufs_xi_release,
6773+ .read = dbgaufs_xi_read
6774+};
6775+
062440b3
AM
6776+void dbgaufs_xino_del(struct au_branch *br)
6777+{
6778+ struct dentry *dbgaufs;
6779+
6780+ dbgaufs = br->br_dbgaufs;
6781+ if (!dbgaufs)
6782+ return;
6783+
6784+ br->br_dbgaufs = NULL;
6785+ /* debugfs acquires the parent i_mutex */
6786+ lockdep_off();
6787+ debugfs_remove(dbgaufs);
6788+ lockdep_on();
6789+}
6790+
1facf9fc 6791+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
6792+{
5afbbe0d 6793+ aufs_bindex_t bbot;
1facf9fc 6794+ struct au_branch *br;
1facf9fc 6795+
6796+ if (!au_sbi(sb)->si_dbgaufs)
6797+ return;
6798+
5afbbe0d
AM
6799+ bbot = au_sbbot(sb);
6800+ for (; bindex <= bbot; bindex++) {
1facf9fc 6801+ br = au_sbr(sb, bindex);
062440b3
AM
6802+ dbgaufs_xino_del(br);
6803+ }
6804+}
6805+
acd2b654
AM
6806+static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex,
6807+ unsigned int idx, struct dentry *parent,
6808+ struct au_sbinfo *sbinfo)
062440b3
AM
6809+{
6810+ struct au_branch *br;
6811+ struct dentry *d;
acd2b654
AM
6812+ /* "xi" bindex(5) "-" idx(2) NULL */
6813+ char name[sizeof(DbgaufsXi_PREFIX) + 8];
062440b3 6814+
acd2b654
AM
6815+ if (!idx)
6816+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
6817+ else
6818+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u",
6819+ bindex, idx);
062440b3
AM
6820+ br = au_sbr(sb, bindex);
6821+ if (br->br_dbgaufs) {
6822+ struct qstr qstr = QSTR_INIT(name, strlen(name));
6823+
6824+ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) {
6825+ /* debugfs acquires the parent i_mutex */
6826+ lockdep_off();
6827+ d = debugfs_rename(parent, br->br_dbgaufs, parent,
6828+ name);
6829+ lockdep_on();
6830+ if (unlikely(!d))
6831+ pr_warn("failed renaming %pd/%s, ignored.\n",
6832+ parent, name);
6833+ }
6834+ } else {
e2f27e51 6835+ lockdep_off();
062440b3
AM
6836+ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
6837+ sbinfo, &dbgaufs_xino_fop);
e2f27e51 6838+ lockdep_on();
062440b3 6839+ if (unlikely(!br->br_dbgaufs))
acd2b654 6840+ pr_warn("failed creating %pd/%s, ignored.\n",
062440b3 6841+ parent, name);
1facf9fc 6842+ }
6843+}
6844+
acd2b654
AM
6845+static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex,
6846+ struct dentry *parent, struct au_sbinfo *sbinfo)
6847+{
6848+ struct au_branch *br;
6849+ struct au_xino *xi;
6850+ unsigned int u;
6851+
6852+ br = au_sbr(sb, bindex);
6853+ xi = br->br_xino;
6854+ for (u = 0; u < xi->xi_nfile; u++)
6855+ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo);
6856+}
6857+
062440b3 6858+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown)
1facf9fc 6859+{
6860+ struct au_sbinfo *sbinfo;
6861+ struct dentry *parent;
5afbbe0d 6862+ aufs_bindex_t bbot;
062440b3
AM
6863+
6864+ if (!au_opt_test(au_mntflags(sb), XINO))
6865+ return;
1facf9fc 6866+
6867+ sbinfo = au_sbi(sb);
6868+ parent = sbinfo->si_dbgaufs;
6869+ if (!parent)
6870+ return;
6871+
5afbbe0d 6872+ bbot = au_sbbot(sb);
062440b3
AM
6873+ if (topdown)
6874+ for (; bindex <= bbot; bindex++)
6875+ dbgaufs_br_add(sb, bindex, parent, sbinfo);
6876+ else
6877+ for (; bbot >= bindex; bbot--)
6878+ dbgaufs_br_add(sb, bbot, parent, sbinfo);
1facf9fc 6879+}
6880+
6881+/* ---------------------------------------------------------------------- */
6882+
6883+#ifdef CONFIG_AUFS_EXPORT
6884+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
6885+{
6886+ int err;
6887+ struct au_sbinfo *sbinfo;
6888+ struct super_block *sb;
6889+
6890+ sbinfo = inode->i_private;
6891+ sb = sbinfo->si_sb;
6892+ si_noflush_read_lock(sb);
062440b3 6893+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6894+ si_read_unlock(sb);
6895+ return err;
6896+}
6897+
6898+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 6899+ .owner = THIS_MODULE,
1facf9fc 6900+ .open = dbgaufs_xigen_open,
6901+ .release = dbgaufs_xi_release,
6902+ .read = dbgaufs_xi_read
6903+};
6904+
6905+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6906+{
6907+ int err;
6908+
dece6358 6909+ /*
c1595e42 6910+ * This function is a dynamic '__init' function actually,
dece6358
AM
6911+ * so the tiny check for si_rwsem is unnecessary.
6912+ */
6913+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6914+
1facf9fc 6915+ err = -EIO;
6916+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
6917+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6918+ &dbgaufs_xigen_fop);
6919+ if (sbinfo->si_dbgaufs_xigen)
6920+ err = 0;
6921+
6922+ return err;
6923+}
6924+#else
6925+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6926+{
6927+ return 0;
6928+}
6929+#endif /* CONFIG_AUFS_EXPORT */
6930+
6931+/* ---------------------------------------------------------------------- */
6932+
6933+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
6934+{
dece6358 6935+ /*
7e9cd9fe 6936+ * This function is a dynamic '__fin' function actually,
dece6358
AM
6937+ * so the tiny check for si_rwsem is unnecessary.
6938+ */
6939+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6940+
1facf9fc 6941+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
6942+ sbinfo->si_dbgaufs = NULL;
1facf9fc 6943+}
6944+
6945+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
6946+{
6947+ int err;
6948+ char name[SysaufsSiNameLen];
6949+
dece6358 6950+ /*
c1595e42 6951+ * This function is a dynamic '__init' function actually,
dece6358
AM
6952+ * so the tiny check for si_rwsem is unnecessary.
6953+ */
6954+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6955+
1facf9fc 6956+ err = -ENOENT;
6957+ if (!dbgaufs) {
6958+ AuErr1("/debug/aufs is uninitialized\n");
6959+ goto out;
6960+ }
6961+
6962+ err = -EIO;
6963+ sysaufs_name(sbinfo, name);
6964+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
6965+ if (unlikely(!sbinfo->si_dbgaufs))
6966+ goto out;
1facf9fc 6967+
062440b3 6968+ /* regardless plink/noplink option */
86dc4139
AM
6969+ sbinfo->si_dbgaufs_plink = debugfs_create_file
6970+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6971+ &dbgaufs_plink_fop);
6972+ if (unlikely(!sbinfo->si_dbgaufs_plink))
6973+ goto out_dir;
6974+
062440b3
AM
6975+ /* regardless xino/noxino option */
6976+ sbinfo->si_dbgaufs_xib = debugfs_create_file
6977+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6978+ &dbgaufs_xib_fop);
6979+ if (unlikely(!sbinfo->si_dbgaufs_xib))
6980+ goto out_dir;
6981+
1facf9fc 6982+ err = dbgaufs_xigen_init(sbinfo);
6983+ if (!err)
6984+ goto out; /* success */
6985+
4f0767ce 6986+out_dir:
1facf9fc 6987+ dbgaufs_si_fin(sbinfo);
4f0767ce 6988+out:
062440b3
AM
6989+ if (unlikely(err))
6990+ pr_err("debugfs/aufs failed\n");
1facf9fc 6991+ return err;
6992+}
6993+
6994+/* ---------------------------------------------------------------------- */
6995+
6996+void dbgaufs_fin(void)
6997+{
6998+ debugfs_remove(dbgaufs);
6999+}
7000+
7001+int __init dbgaufs_init(void)
7002+{
7003+ int err;
7004+
7005+ err = -EIO;
7006+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
7007+ if (dbgaufs)
7008+ err = 0;
7009+ return err;
7010+}
7f207e10 7011diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
fbc438ed
JR
7012--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 08:00:00.000000000 +0800
7013+++ linux/fs/aufs/dbgaufs.h 2019-07-11 21:21:54.379051070 +0800
062440b3
AM
7014@@ -0,0 +1,53 @@
7015+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7016+/*
ba1aed25 7017+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7018+ *
7019+ * This program, aufs is free software; you can redistribute it and/or modify
7020+ * it under the terms of the GNU General Public License as published by
7021+ * the Free Software Foundation; either version 2 of the License, or
7022+ * (at your option) any later version.
dece6358
AM
7023+ *
7024+ * This program is distributed in the hope that it will be useful,
7025+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7026+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7027+ * GNU General Public License for more details.
7028+ *
7029+ * You should have received a copy of the GNU General Public License
523b37e3 7030+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7031+ */
7032+
7033+/*
7034+ * debugfs interface
7035+ */
7036+
7037+#ifndef __DBGAUFS_H__
7038+#define __DBGAUFS_H__
7039+
7040+#ifdef __KERNEL__
7041+
dece6358 7042+struct super_block;
1facf9fc 7043+struct au_sbinfo;
062440b3 7044+struct au_branch;
dece6358 7045+
1facf9fc 7046+#ifdef CONFIG_DEBUG_FS
7047+/* dbgaufs.c */
062440b3 7048+void dbgaufs_xino_del(struct au_branch *br);
1facf9fc 7049+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
062440b3 7050+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown);
1facf9fc 7051+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
7052+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
7053+void dbgaufs_fin(void);
7054+int __init dbgaufs_init(void);
1facf9fc 7055+#else
062440b3 7056+AuStubVoid(dbgaufs_xino_del, struct au_branch *br)
4a4d8108 7057+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
062440b3
AM
7058+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex,
7059+ int topdown)
4a4d8108
AM
7060+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
7061+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
7062+AuStubVoid(dbgaufs_fin, void)
7063+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 7064+#endif /* CONFIG_DEBUG_FS */
7065+
7066+#endif /* __KERNEL__ */
7067+#endif /* __DBGAUFS_H__ */
7f207e10 7068diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
fbc438ed
JR
7069--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 08:00:00.000000000 +0800
7070+++ linux/fs/aufs/dcsub.c 2019-07-11 21:21:54.379051070 +0800
cd7a4cd9
AM
7071@@ -0,0 +1,225 @@
7072+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7073+/*
ba1aed25 7074+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7075+ *
7076+ * This program, aufs is free software; you can redistribute it and/or modify
7077+ * it under the terms of the GNU General Public License as published by
7078+ * the Free Software Foundation; either version 2 of the License, or
7079+ * (at your option) any later version.
dece6358
AM
7080+ *
7081+ * This program is distributed in the hope that it will be useful,
7082+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7083+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7084+ * GNU General Public License for more details.
7085+ *
7086+ * You should have received a copy of the GNU General Public License
523b37e3 7087+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7088+ */
7089+
7090+/*
7091+ * sub-routines for dentry cache
7092+ */
7093+
7094+#include "aufs.h"
7095+
7096+static void au_dpage_free(struct au_dpage *dpage)
7097+{
7098+ int i;
7099+ struct dentry **p;
7100+
7101+ p = dpage->dentries;
7102+ for (i = 0; i < dpage->ndentry; i++)
7103+ dput(*p++);
1c60b727 7104+ free_page((unsigned long)dpage->dentries);
1facf9fc 7105+}
7106+
7107+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
7108+{
7109+ int err;
7110+ void *p;
7111+
7112+ err = -ENOMEM;
7113+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
7114+ if (unlikely(!dpages->dpages))
7115+ goto out;
7116+
7117+ p = (void *)__get_free_page(gfp);
7118+ if (unlikely(!p))
7119+ goto out_dpages;
7120+
7121+ dpages->dpages[0].ndentry = 0;
7122+ dpages->dpages[0].dentries = p;
7123+ dpages->ndpage = 1;
7124+ return 0; /* success */
7125+
4f0767ce 7126+out_dpages:
9f237c51 7127+ au_kfree_try_rcu(dpages->dpages);
4f0767ce 7128+out:
1facf9fc 7129+ return err;
7130+}
7131+
7132+void au_dpages_free(struct au_dcsub_pages *dpages)
7133+{
7134+ int i;
7135+ struct au_dpage *p;
7136+
7137+ p = dpages->dpages;
7138+ for (i = 0; i < dpages->ndpage; i++)
7139+ au_dpage_free(p++);
9f237c51 7140+ au_kfree_try_rcu(dpages->dpages);
1facf9fc 7141+}
7142+
7143+static int au_dpages_append(struct au_dcsub_pages *dpages,
7144+ struct dentry *dentry, gfp_t gfp)
7145+{
7146+ int err, sz;
7147+ struct au_dpage *dpage;
7148+ void *p;
7149+
7150+ dpage = dpages->dpages + dpages->ndpage - 1;
7151+ sz = PAGE_SIZE / sizeof(dentry);
7152+ if (unlikely(dpage->ndentry >= sz)) {
7153+ AuLabel(new dpage);
7154+ err = -ENOMEM;
7155+ sz = dpages->ndpage * sizeof(*dpages->dpages);
7156+ p = au_kzrealloc(dpages->dpages, sz,
e2f27e51
AM
7157+ sz + sizeof(*dpages->dpages), gfp,
7158+ /*may_shrink*/0);
1facf9fc 7159+ if (unlikely(!p))
7160+ goto out;
7161+
7162+ dpages->dpages = p;
7163+ dpage = dpages->dpages + dpages->ndpage;
7164+ p = (void *)__get_free_page(gfp);
7165+ if (unlikely(!p))
7166+ goto out;
7167+
7168+ dpage->ndentry = 0;
7169+ dpage->dentries = p;
7170+ dpages->ndpage++;
7171+ }
7172+
c1595e42 7173+ AuDebugOn(au_dcount(dentry) <= 0);
027c5e7a 7174+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 7175+ return 0; /* success */
7176+
4f0767ce 7177+out:
1facf9fc 7178+ return err;
7179+}
7180+
c1595e42
JR
7181+/* todo: BAD approach */
7182+/* copied from linux/fs/dcache.c */
7183+enum d_walk_ret {
7184+ D_WALK_CONTINUE,
7185+ D_WALK_QUIT,
7186+ D_WALK_NORETRY,
7187+ D_WALK_SKIP,
7188+};
7189+
7190+extern void d_walk(struct dentry *parent, void *data,
cd7a4cd9 7191+ enum d_walk_ret (*enter)(void *, struct dentry *));
c1595e42
JR
7192+
7193+struct ac_dpages_arg {
1facf9fc 7194+ int err;
c1595e42
JR
7195+ struct au_dcsub_pages *dpages;
7196+ struct super_block *sb;
7197+ au_dpages_test test;
7198+ void *arg;
7199+};
1facf9fc 7200+
c1595e42
JR
7201+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry)
7202+{
7203+ enum d_walk_ret ret;
7204+ struct ac_dpages_arg *arg = _arg;
1facf9fc 7205+
c1595e42
JR
7206+ ret = D_WALK_CONTINUE;
7207+ if (dentry->d_sb == arg->sb
7208+ && !IS_ROOT(dentry)
7209+ && au_dcount(dentry) > 0
7210+ && au_di(dentry)
7211+ && (!arg->test || arg->test(dentry, arg->arg))) {
7212+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC);
7213+ if (unlikely(arg->err))
7214+ ret = D_WALK_QUIT;
1facf9fc 7215+ }
7216+
c1595e42
JR
7217+ return ret;
7218+}
027c5e7a 7219+
c1595e42
JR
7220+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7221+ au_dpages_test test, void *arg)
7222+{
7223+ struct ac_dpages_arg args = {
7224+ .err = 0,
7225+ .dpages = dpages,
7226+ .sb = root->d_sb,
7227+ .test = test,
7228+ .arg = arg
7229+ };
027c5e7a 7230+
cd7a4cd9 7231+ d_walk(root, &args, au_call_dpages_append);
c1595e42
JR
7232+
7233+ return args.err;
1facf9fc 7234+}
7235+
7236+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7237+ int do_include, au_dpages_test test, void *arg)
7238+{
7239+ int err;
7240+
7241+ err = 0;
027c5e7a
AM
7242+ write_seqlock(&rename_lock);
7243+ spin_lock(&dentry->d_lock);
7244+ if (do_include
c1595e42 7245+ && au_dcount(dentry) > 0
027c5e7a 7246+ && (!test || test(dentry, arg)))
1facf9fc 7247+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7248+ spin_unlock(&dentry->d_lock);
7249+ if (unlikely(err))
7250+ goto out;
7251+
7252+ /*
523b37e3 7253+ * RCU for vfsmount is unnecessary since this is a traverse in a single
027c5e7a
AM
7254+ * mount
7255+ */
1facf9fc 7256+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
7257+ dentry = dentry->d_parent; /* rename_lock is locked */
7258+ spin_lock(&dentry->d_lock);
c1595e42 7259+ if (au_dcount(dentry) > 0
027c5e7a 7260+ && (!test || test(dentry, arg)))
1facf9fc 7261+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7262+ spin_unlock(&dentry->d_lock);
7263+ if (unlikely(err))
7264+ break;
1facf9fc 7265+ }
7266+
4f0767ce 7267+out:
027c5e7a 7268+ write_sequnlock(&rename_lock);
1facf9fc 7269+ return err;
7270+}
7271+
027c5e7a
AM
7272+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
7273+{
7274+ return au_di(dentry) && dentry->d_sb == arg;
7275+}
7276+
7277+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7278+ struct dentry *dentry, int do_include)
7279+{
7280+ return au_dcsub_pages_rev(dpages, dentry, do_include,
7281+ au_dcsub_dpages_aufs, dentry->d_sb);
7282+}
7283+
4a4d8108 7284+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 7285+{
4a4d8108
AM
7286+ struct path path[2] = {
7287+ {
7288+ .dentry = d1
7289+ },
7290+ {
7291+ .dentry = d2
7292+ }
7293+ };
1facf9fc 7294+
4a4d8108 7295+ return path_is_under(path + 0, path + 1);
1facf9fc 7296+}
7f207e10 7297diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
fbc438ed
JR
7298--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 08:00:00.000000000 +0800
7299+++ linux/fs/aufs/dcsub.h 2019-07-11 21:21:54.379051070 +0800
062440b3
AM
7300@@ -0,0 +1,137 @@
7301+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7302+/*
ba1aed25 7303+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7304+ *
7305+ * This program, aufs is free software; you can redistribute it and/or modify
7306+ * it under the terms of the GNU General Public License as published by
7307+ * the Free Software Foundation; either version 2 of the License, or
7308+ * (at your option) any later version.
dece6358
AM
7309+ *
7310+ * This program is distributed in the hope that it will be useful,
7311+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7312+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7313+ * GNU General Public License for more details.
7314+ *
7315+ * You should have received a copy of the GNU General Public License
523b37e3 7316+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7317+ */
7318+
7319+/*
7320+ * sub-routines for dentry cache
7321+ */
7322+
7323+#ifndef __AUFS_DCSUB_H__
7324+#define __AUFS_DCSUB_H__
7325+
7326+#ifdef __KERNEL__
7327+
7f207e10 7328+#include <linux/dcache.h>
027c5e7a 7329+#include <linux/fs.h>
dece6358 7330+
1facf9fc 7331+struct au_dpage {
7332+ int ndentry;
7333+ struct dentry **dentries;
7334+};
7335+
7336+struct au_dcsub_pages {
7337+ int ndpage;
7338+ struct au_dpage *dpages;
7339+};
7340+
7341+/* ---------------------------------------------------------------------- */
7342+
7f207e10 7343+/* dcsub.c */
1facf9fc 7344+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
7345+void au_dpages_free(struct au_dcsub_pages *dpages);
7346+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
7347+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7348+ au_dpages_test test, void *arg);
7349+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7350+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
7351+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7352+ struct dentry *dentry, int do_include);
4a4d8108 7353+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 7354+
7f207e10
AM
7355+/* ---------------------------------------------------------------------- */
7356+
523b37e3
AM
7357+/*
7358+ * todo: in linux-3.13, several similar (but faster) helpers are added to
7359+ * include/linux/dcache.h. Try them (in the future).
7360+ */
7361+
027c5e7a
AM
7362+static inline int au_d_hashed_positive(struct dentry *d)
7363+{
7364+ int err;
5527c038 7365+ struct inode *inode = d_inode(d);
076b876e 7366+
027c5e7a 7367+ err = 0;
5527c038
JR
7368+ if (unlikely(d_unhashed(d)
7369+ || d_is_negative(d)
7370+ || !inode->i_nlink))
027c5e7a
AM
7371+ err = -ENOENT;
7372+ return err;
7373+}
7374+
38d290e6
JR
7375+static inline int au_d_linkable(struct dentry *d)
7376+{
7377+ int err;
5527c038 7378+ struct inode *inode = d_inode(d);
076b876e 7379+
38d290e6
JR
7380+ err = au_d_hashed_positive(d);
7381+ if (err
5527c038 7382+ && d_is_positive(d)
38d290e6
JR
7383+ && (inode->i_state & I_LINKABLE))
7384+ err = 0;
7385+ return err;
7386+}
7387+
027c5e7a
AM
7388+static inline int au_d_alive(struct dentry *d)
7389+{
7390+ int err;
7391+ struct inode *inode;
076b876e 7392+
027c5e7a
AM
7393+ err = 0;
7394+ if (!IS_ROOT(d))
7395+ err = au_d_hashed_positive(d);
7396+ else {
5527c038
JR
7397+ inode = d_inode(d);
7398+ if (unlikely(d_unlinked(d)
7399+ || d_is_negative(d)
7400+ || !inode->i_nlink))
027c5e7a
AM
7401+ err = -ENOENT;
7402+ }
7403+ return err;
7404+}
7405+
7406+static inline int au_alive_dir(struct dentry *d)
7f207e10 7407+{
027c5e7a 7408+ int err;
076b876e 7409+
027c5e7a 7410+ err = au_d_alive(d);
5527c038 7411+ if (unlikely(err || IS_DEADDIR(d_inode(d))))
027c5e7a
AM
7412+ err = -ENOENT;
7413+ return err;
7f207e10
AM
7414+}
7415+
38d290e6
JR
7416+static inline int au_qstreq(struct qstr *a, struct qstr *b)
7417+{
7418+ return a->len == b->len
7419+ && !memcmp(a->name, b->name, a->len);
7420+}
7421+
7e9cd9fe
AM
7422+/*
7423+ * by the commit
7424+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without
7425+ * taking d_lock
7426+ * the type of d_lockref.count became int, but the inlined function d_count()
7427+ * still returns unsigned int.
7428+ * I don't know why. Maybe it is for every d_count() users?
7429+ * Anyway au_dcount() lives on.
7430+ */
c1595e42
JR
7431+static inline int au_dcount(struct dentry *d)
7432+{
7433+ return (int)d_count(d);
7434+}
7435+
1facf9fc 7436+#endif /* __KERNEL__ */
7437+#endif /* __AUFS_DCSUB_H__ */
7f207e10 7438diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
fbc438ed
JR
7439--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 08:00:00.000000000 +0800
7440+++ linux/fs/aufs/debug.c 2019-07-11 21:21:54.379051070 +0800
eca801bf 7441@@ -0,0 +1,441 @@
cd7a4cd9 7442+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7443+/*
ba1aed25 7444+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7445+ *
7446+ * This program, aufs is free software; you can redistribute it and/or modify
7447+ * it under the terms of the GNU General Public License as published by
7448+ * the Free Software Foundation; either version 2 of the License, or
7449+ * (at your option) any later version.
dece6358
AM
7450+ *
7451+ * This program is distributed in the hope that it will be useful,
7452+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7453+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7454+ * GNU General Public License for more details.
7455+ *
7456+ * You should have received a copy of the GNU General Public License
523b37e3 7457+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7458+ */
7459+
7460+/*
7461+ * debug print functions
7462+ */
7463+
eca801bf 7464+#include <linux/iversion.h>
1facf9fc 7465+#include "aufs.h"
7466+
392086de
AM
7467+/* Returns 0, or -errno. arg is in kp->arg. */
7468+static int param_atomic_t_set(const char *val, const struct kernel_param *kp)
7469+{
7470+ int err, n;
7471+
7472+ err = kstrtoint(val, 0, &n);
7473+ if (!err) {
7474+ if (n > 0)
7475+ au_debug_on();
7476+ else
7477+ au_debug_off();
7478+ }
7479+ return err;
7480+}
7481+
7482+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
7483+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp)
7484+{
7485+ atomic_t *a;
7486+
7487+ a = kp->arg;
7488+ return sprintf(buffer, "%d", atomic_read(a));
7489+}
7490+
7491+static struct kernel_param_ops param_ops_atomic_t = {
7492+ .set = param_atomic_t_set,
7493+ .get = param_atomic_t_get
7494+ /* void (*free)(void *arg) */
7495+};
7496+
7497+atomic_t aufs_debug = ATOMIC_INIT(0);
1facf9fc 7498+MODULE_PARM_DESC(debug, "debug print");
cd7a4cd9 7499+module_param_named(debug, aufs_debug, atomic_t, 0664);
1facf9fc 7500+
c1595e42 7501+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */
1facf9fc 7502+char *au_plevel = KERN_DEBUG;
e49829fe
JR
7503+#define dpri(fmt, ...) do { \
7504+ if ((au_plevel \
7505+ && strcmp(au_plevel, KERN_DEBUG)) \
7506+ || au_debug_test()) \
7507+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 7508+} while (0)
7509+
7510+/* ---------------------------------------------------------------------- */
7511+
7512+void au_dpri_whlist(struct au_nhash *whlist)
7513+{
7514+ unsigned long ul, n;
7515+ struct hlist_head *head;
c06a8ce3 7516+ struct au_vdir_wh *pos;
1facf9fc 7517+
7518+ n = whlist->nh_num;
7519+ head = whlist->nh_head;
7520+ for (ul = 0; ul < n; ul++) {
c06a8ce3 7521+ hlist_for_each_entry(pos, head, wh_hash)
1facf9fc 7522+ dpri("b%d, %.*s, %d\n",
c06a8ce3
AM
7523+ pos->wh_bindex,
7524+ pos->wh_str.len, pos->wh_str.name,
7525+ pos->wh_str.len);
1facf9fc 7526+ head++;
7527+ }
7528+}
7529+
7530+void au_dpri_vdir(struct au_vdir *vdir)
7531+{
7532+ unsigned long ul;
7533+ union au_vdir_deblk_p p;
7534+ unsigned char *o;
7535+
7536+ if (!vdir || IS_ERR(vdir)) {
7537+ dpri("err %ld\n", PTR_ERR(vdir));
7538+ return;
7539+ }
7540+
be118d29 7541+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n",
1facf9fc 7542+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
7543+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
7544+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
7545+ p.deblk = vdir->vd_deblk[ul];
7546+ o = p.deblk;
7547+ dpri("[%lu]: %p\n", ul, o);
7548+ }
7549+}
7550+
53392da6 7551+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 7552+ struct dentry *wh)
7553+{
7554+ char *n = NULL;
7555+ int l = 0;
7556+
7557+ if (!inode || IS_ERR(inode)) {
7558+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
7559+ return -1;
7560+ }
7561+
c2b27bf2 7562+ /* the type of i_blocks depends upon CONFIG_LBDAF */
1facf9fc 7563+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
7564+ && sizeof(inode->i_blocks) != sizeof(u64));
7565+ if (wh) {
7566+ n = (void *)wh->d_name.name;
7567+ l = wh->d_name.len;
7568+ }
7569+
53392da6
AM
7570+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
7571+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
7572+ bindex, inode,
1facf9fc 7573+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
7574+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
7575+ i_size_read(inode), (unsigned long long)inode->i_blocks,
cd7a4cd9 7576+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 7577+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
be118d29 7578+ inode->i_state, inode->i_flags, inode_peek_iversion(inode),
b752ccd1 7579+ inode->i_generation,
1facf9fc 7580+ l ? ", wh " : "", l, n);
7581+ return 0;
7582+}
7583+
7584+void au_dpri_inode(struct inode *inode)
7585+{
7586+ struct au_iinfo *iinfo;
5afbbe0d 7587+ struct au_hinode *hi;
1facf9fc 7588+ aufs_bindex_t bindex;
53392da6 7589+ int err, hn;
1facf9fc 7590+
53392da6 7591+ err = do_pri_inode(-1, inode, -1, NULL);
5afbbe0d 7592+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode))
1facf9fc 7593+ return;
7594+
7595+ iinfo = au_ii(inode);
5afbbe0d
AM
7596+ dpri("i-1: btop %d, bbot %d, gen %d\n",
7597+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL));
7598+ if (iinfo->ii_btop < 0)
1facf9fc 7599+ return;
53392da6 7600+ hn = 0;
5afbbe0d
AM
7601+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) {
7602+ hi = au_hinode(iinfo, bindex);
7603+ hn = !!au_hn(hi);
7604+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry);
53392da6 7605+ }
1facf9fc 7606+}
7607+
2cbb1c4b
JR
7608+void au_dpri_dalias(struct inode *inode)
7609+{
7610+ struct dentry *d;
7611+
7612+ spin_lock(&inode->i_lock);
c1595e42 7613+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias)
2cbb1c4b
JR
7614+ au_dpri_dentry(d);
7615+ spin_unlock(&inode->i_lock);
7616+}
7617+
1facf9fc 7618+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
7619+{
7620+ struct dentry *wh = NULL;
53392da6 7621+ int hn;
5afbbe0d 7622+ struct inode *inode;
076b876e 7623+ struct au_iinfo *iinfo;
5afbbe0d 7624+ struct au_hinode *hi;
1facf9fc 7625+
7626+ if (!dentry || IS_ERR(dentry)) {
7627+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
7628+ return -1;
7629+ }
7630+ /* do not call dget_parent() here */
027c5e7a 7631+ /* note: access d_xxx without d_lock */
523b37e3
AM
7632+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n",
7633+ bindex, dentry, dentry,
1facf9fc 7634+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
c1595e42 7635+ au_dcount(dentry), dentry->d_flags,
523b37e3 7636+ d_unhashed(dentry) ? "un" : "");
53392da6 7637+ hn = -1;
5afbbe0d
AM
7638+ inode = NULL;
7639+ if (d_is_positive(dentry))
7640+ inode = d_inode(dentry);
7641+ if (inode
7642+ && au_test_aufs(dentry->d_sb)
7643+ && bindex >= 0
7644+ && !au_is_bad_inode(inode)) {
7645+ iinfo = au_ii(inode);
7646+ hi = au_hinode(iinfo, bindex);
7647+ hn = !!au_hn(hi);
7648+ wh = hi->hi_whdentry;
7649+ }
7650+ do_pri_inode(bindex, inode, hn, wh);
1facf9fc 7651+ return 0;
7652+}
7653+
7654+void au_dpri_dentry(struct dentry *dentry)
7655+{
7656+ struct au_dinfo *dinfo;
7657+ aufs_bindex_t bindex;
7658+ int err;
7659+
7660+ err = do_pri_dentry(-1, dentry);
7661+ if (err || !au_test_aufs(dentry->d_sb))
7662+ return;
7663+
7664+ dinfo = au_di(dentry);
7665+ if (!dinfo)
7666+ return;
5afbbe0d
AM
7667+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n",
7668+ dinfo->di_btop, dinfo->di_bbot,
38d290e6
JR
7669+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry),
7670+ dinfo->di_tmpfile);
5afbbe0d 7671+ if (dinfo->di_btop < 0)
1facf9fc 7672+ return;
5afbbe0d
AM
7673+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++)
7674+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry);
1facf9fc 7675+}
7676+
7677+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
7678+{
7679+ char a[32];
7680+
7681+ if (!file || IS_ERR(file)) {
7682+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
7683+ return -1;
7684+ }
7685+ a[0] = 0;
7686+ if (bindex < 0
b912730e 7687+ && !IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7688+ && au_test_aufs(file->f_path.dentry->d_sb)
1facf9fc 7689+ && au_fi(file))
e49829fe 7690+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 7691+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 7692+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 7693+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 7694+ file->f_version, file->f_pos, a);
b912730e 7695+ if (!IS_ERR_OR_NULL(file->f_path.dentry))
2000de60 7696+ do_pri_dentry(bindex, file->f_path.dentry);
1facf9fc 7697+ return 0;
7698+}
7699+
7700+void au_dpri_file(struct file *file)
7701+{
7702+ struct au_finfo *finfo;
4a4d8108
AM
7703+ struct au_fidir *fidir;
7704+ struct au_hfile *hfile;
1facf9fc 7705+ aufs_bindex_t bindex;
7706+ int err;
7707+
7708+ err = do_pri_file(-1, file);
2000de60 7709+ if (err
b912730e 7710+ || IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7711+ || !au_test_aufs(file->f_path.dentry->d_sb))
1facf9fc 7712+ return;
7713+
7714+ finfo = au_fi(file);
7715+ if (!finfo)
7716+ return;
4a4d8108 7717+ if (finfo->fi_btop < 0)
1facf9fc 7718+ return;
4a4d8108
AM
7719+ fidir = finfo->fi_hdir;
7720+ if (!fidir)
7721+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
7722+ else
e49829fe
JR
7723+ for (bindex = finfo->fi_btop;
7724+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
7725+ bindex++) {
7726+ hfile = fidir->fd_hfile + bindex;
7727+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
7728+ }
1facf9fc 7729+}
7730+
7731+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
7732+{
7733+ struct vfsmount *mnt;
7734+ struct super_block *sb;
7735+
7736+ if (!br || IS_ERR(br))
7737+ goto out;
86dc4139 7738+ mnt = au_br_mnt(br);
1facf9fc 7739+ if (!mnt || IS_ERR(mnt))
7740+ goto out;
7741+ sb = mnt->mnt_sb;
7742+ if (!sb || IS_ERR(sb))
7743+ goto out;
7744+
acd2b654 7745+ dpri("s%d: {perm 0x%x, id %d, wbr %p}, "
b752ccd1 7746+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 7747+ "xino %d\n",
acd2b654
AM
7748+ bindex, br->br_perm, br->br_id, br->br_wbr,
7749+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 7750+ sb->s_flags, sb->s_count,
acd2b654
AM
7751+ atomic_read(&sb->s_active),
7752+ !!au_xino_file(br->br_xino, /*idx*/-1));
1facf9fc 7753+ return 0;
7754+
4f0767ce 7755+out:
1facf9fc 7756+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
7757+ return -1;
7758+}
7759+
7760+void au_dpri_sb(struct super_block *sb)
7761+{
7762+ struct au_sbinfo *sbinfo;
7763+ aufs_bindex_t bindex;
7764+ int err;
acd2b654 7765+ /* to reduce stack size */
1facf9fc 7766+ struct {
7767+ struct vfsmount mnt;
7768+ struct au_branch fake;
7769+ } *a;
7770+
7771+ /* this function can be called from magic sysrq */
7772+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
7773+ if (unlikely(!a)) {
7774+ dpri("no memory\n");
7775+ return;
7776+ }
7777+
7778+ a->mnt.mnt_sb = sb;
86dc4139 7779+ a->fake.br_path.mnt = &a->mnt;
1facf9fc 7780+ err = do_pri_br(-1, &a->fake);
9f237c51 7781+ au_kfree_rcu(a);
1facf9fc 7782+ dpri("dev 0x%x\n", sb->s_dev);
7783+ if (err || !au_test_aufs(sb))
7784+ return;
7785+
7786+ sbinfo = au_sbi(sb);
7787+ if (!sbinfo)
7788+ return;
f0c0a007
AM
7789+ dpri("nw %d, gen %u, kobj %d\n",
7790+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
521ced18 7791+ kref_read(&sbinfo->si_kobj.kref));
5afbbe0d 7792+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++)
1facf9fc 7793+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
7794+}
7795+
7796+/* ---------------------------------------------------------------------- */
7797+
027c5e7a
AM
7798+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
7799+{
5527c038 7800+ struct inode *h_inode, *inode = d_inode(dentry);
027c5e7a 7801+ struct dentry *h_dentry;
5afbbe0d 7802+ aufs_bindex_t bindex, bbot, bi;
027c5e7a
AM
7803+
7804+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
7805+ return;
7806+
5afbbe0d
AM
7807+ bbot = au_dbbot(dentry);
7808+ bi = au_ibbot(inode);
7809+ if (bi < bbot)
7810+ bbot = bi;
7811+ bindex = au_dbtop(dentry);
7812+ bi = au_ibtop(inode);
027c5e7a
AM
7813+ if (bi > bindex)
7814+ bindex = bi;
7815+
5afbbe0d 7816+ for (; bindex <= bbot; bindex++) {
027c5e7a
AM
7817+ h_dentry = au_h_dptr(dentry, bindex);
7818+ if (!h_dentry)
7819+ continue;
7820+ h_inode = au_h_iptr(inode, bindex);
5527c038 7821+ if (unlikely(h_inode != d_inode(h_dentry))) {
392086de 7822+ au_debug_on();
027c5e7a
AM
7823+ AuDbg("b%d, %s:%d\n", bindex, func, line);
7824+ AuDbgDentry(dentry);
7825+ AuDbgInode(inode);
392086de 7826+ au_debug_off();
027c5e7a
AM
7827+ BUG();
7828+ }
7829+ }
7830+}
7831+
1facf9fc 7832+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
7833+{
7834+ int err, i, j;
7835+ struct au_dcsub_pages dpages;
7836+ struct au_dpage *dpage;
7837+ struct dentry **dentries;
7838+
7839+ err = au_dpages_init(&dpages, GFP_NOFS);
7840+ AuDebugOn(err);
027c5e7a 7841+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 7842+ AuDebugOn(err);
7843+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
7844+ dpage = dpages.dpages + i;
7845+ dentries = dpage->dentries;
7846+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 7847+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 7848+ }
7849+ au_dpages_free(&dpages);
7850+}
7851+
1facf9fc 7852+void au_dbg_verify_kthread(void)
7853+{
53392da6 7854+ if (au_wkq_test()) {
1facf9fc 7855+ au_dbg_blocked();
1e00d052
AM
7856+ /*
7857+ * It may be recursive, but udba=notify between two aufs mounts,
7858+ * where a single ro branch is shared, is not a problem.
7859+ */
7860+ /* WARN_ON(1); */
1facf9fc 7861+ }
7862+}
7863+
7864+/* ---------------------------------------------------------------------- */
7865+
1facf9fc 7866+int __init au_debug_init(void)
7867+{
7868+ aufs_bindex_t bindex;
7869+ struct au_vdir_destr destr;
7870+
7871+ bindex = -1;
7872+ AuDebugOn(bindex >= 0);
7873+
7874+ destr.len = -1;
7875+ AuDebugOn(destr.len < NAME_MAX);
7876+
7877+#ifdef CONFIG_4KSTACKS
0c3ec466 7878+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 7879+#endif
7880+
1facf9fc 7881+ return 0;
7882+}
7f207e10 7883diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
fbc438ed
JR
7884--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 08:00:00.000000000 +0800
7885+++ linux/fs/aufs/debug.h 2019-07-11 21:21:54.379051070 +0800
062440b3
AM
7886@@ -0,0 +1,226 @@
7887+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7888+/*
ba1aed25 7889+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 7890+ *
7891+ * This program, aufs is free software; you can redistribute it and/or modify
7892+ * it under the terms of the GNU General Public License as published by
7893+ * the Free Software Foundation; either version 2 of the License, or
7894+ * (at your option) any later version.
dece6358
AM
7895+ *
7896+ * This program is distributed in the hope that it will be useful,
7897+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7898+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7899+ * GNU General Public License for more details.
7900+ *
7901+ * You should have received a copy of the GNU General Public License
523b37e3 7902+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7903+ */
7904+
7905+/*
7906+ * debug print functions
7907+ */
7908+
7909+#ifndef __AUFS_DEBUG_H__
7910+#define __AUFS_DEBUG_H__
7911+
7912+#ifdef __KERNEL__
7913+
392086de 7914+#include <linux/atomic.h>
4a4d8108
AM
7915+#include <linux/module.h>
7916+#include <linux/kallsyms.h>
1facf9fc 7917+#include <linux/sysrq.h>
4a4d8108 7918+
1facf9fc 7919+#ifdef CONFIG_AUFS_DEBUG
7920+#define AuDebugOn(a) BUG_ON(a)
7921+
7922+/* module parameter */
392086de
AM
7923+extern atomic_t aufs_debug;
7924+static inline void au_debug_on(void)
1facf9fc 7925+{
392086de
AM
7926+ atomic_inc(&aufs_debug);
7927+}
7928+static inline void au_debug_off(void)
7929+{
7930+ atomic_dec_if_positive(&aufs_debug);
1facf9fc 7931+}
7932+
7933+static inline int au_debug_test(void)
7934+{
392086de 7935+ return atomic_read(&aufs_debug) > 0;
1facf9fc 7936+}
7937+#else
7938+#define AuDebugOn(a) do {} while (0)
392086de
AM
7939+AuStubVoid(au_debug_on, void)
7940+AuStubVoid(au_debug_off, void)
4a4d8108 7941+AuStubInt0(au_debug_test, void)
1facf9fc 7942+#endif /* CONFIG_AUFS_DEBUG */
7943+
392086de
AM
7944+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t)
7945+
1facf9fc 7946+/* ---------------------------------------------------------------------- */
7947+
7948+/* debug print */
7949+
4a4d8108 7950+#define AuDbg(fmt, ...) do { \
1facf9fc 7951+ if (au_debug_test()) \
4a4d8108 7952+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 7953+} while (0)
4a4d8108
AM
7954+#define AuLabel(l) AuDbg(#l "\n")
7955+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
7956+#define AuWarn1(fmt, ...) do { \
1facf9fc 7957+ static unsigned char _c; \
7958+ if (!_c++) \
0c3ec466 7959+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 7960+} while (0)
7961+
4a4d8108 7962+#define AuErr1(fmt, ...) do { \
1facf9fc 7963+ static unsigned char _c; \
7964+ if (!_c++) \
4a4d8108 7965+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 7966+} while (0)
7967+
4a4d8108 7968+#define AuIOErr1(fmt, ...) do { \
1facf9fc 7969+ static unsigned char _c; \
7970+ if (!_c++) \
4a4d8108 7971+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 7972+} while (0)
7973+
7974+#define AuUnsupportMsg "This operation is not supported." \
7975+ " Please report this application to aufs-users ML."
4a4d8108
AM
7976+#define AuUnsupport(fmt, ...) do { \
7977+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 7978+ dump_stack(); \
7979+} while (0)
7980+
7981+#define AuTraceErr(e) do { \
7982+ if (unlikely((e) < 0)) \
7983+ AuDbg("err %d\n", (int)(e)); \
7984+} while (0)
7985+
7986+#define AuTraceErrPtr(p) do { \
7987+ if (IS_ERR(p)) \
7988+ AuDbg("err %ld\n", PTR_ERR(p)); \
7989+} while (0)
7990+
7991+/* dirty macros for debug print, use with "%.*s" and caution */
7992+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
1facf9fc 7993+
7994+/* ---------------------------------------------------------------------- */
7995+
dece6358 7996+struct dentry;
1facf9fc 7997+#ifdef CONFIG_AUFS_DEBUG
c1595e42 7998+extern struct mutex au_dbg_mtx;
1facf9fc 7999+extern char *au_plevel;
8000+struct au_nhash;
8001+void au_dpri_whlist(struct au_nhash *whlist);
8002+struct au_vdir;
8003+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 8004+struct inode;
1facf9fc 8005+void au_dpri_inode(struct inode *inode);
2cbb1c4b 8006+void au_dpri_dalias(struct inode *inode);
1facf9fc 8007+void au_dpri_dentry(struct dentry *dentry);
dece6358 8008+struct file;
1facf9fc 8009+void au_dpri_file(struct file *filp);
dece6358 8010+struct super_block;
1facf9fc 8011+void au_dpri_sb(struct super_block *sb);
8012+
027c5e7a
AM
8013+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
8014+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 8015+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 8016+void au_dbg_verify_kthread(void);
8017+
8018+int __init au_debug_init(void);
7e9cd9fe 8019+
1facf9fc 8020+#define AuDbgWhlist(w) do { \
c1595e42 8021+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8022+ AuDbg(#w "\n"); \
8023+ au_dpri_whlist(w); \
c1595e42 8024+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8025+} while (0)
8026+
8027+#define AuDbgVdir(v) do { \
c1595e42 8028+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8029+ AuDbg(#v "\n"); \
8030+ au_dpri_vdir(v); \
c1595e42 8031+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8032+} while (0)
8033+
8034+#define AuDbgInode(i) do { \
c1595e42 8035+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8036+ AuDbg(#i "\n"); \
8037+ au_dpri_inode(i); \
c1595e42 8038+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8039+} while (0)
8040+
2cbb1c4b 8041+#define AuDbgDAlias(i) do { \
c1595e42 8042+ mutex_lock(&au_dbg_mtx); \
2cbb1c4b
JR
8043+ AuDbg(#i "\n"); \
8044+ au_dpri_dalias(i); \
c1595e42 8045+ mutex_unlock(&au_dbg_mtx); \
2cbb1c4b
JR
8046+} while (0)
8047+
1facf9fc 8048+#define AuDbgDentry(d) do { \
c1595e42 8049+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8050+ AuDbg(#d "\n"); \
8051+ au_dpri_dentry(d); \
c1595e42 8052+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8053+} while (0)
8054+
8055+#define AuDbgFile(f) do { \
c1595e42 8056+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8057+ AuDbg(#f "\n"); \
8058+ au_dpri_file(f); \
c1595e42 8059+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8060+} while (0)
8061+
8062+#define AuDbgSb(sb) do { \
c1595e42 8063+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8064+ AuDbg(#sb "\n"); \
8065+ au_dpri_sb(sb); \
c1595e42 8066+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8067+} while (0)
8068+
4a4d8108
AM
8069+#define AuDbgSym(addr) do { \
8070+ char sym[KSYM_SYMBOL_LEN]; \
8071+ sprint_symbol(sym, (unsigned long)addr); \
8072+ AuDbg("%s\n", sym); \
8073+} while (0)
1facf9fc 8074+#else
027c5e7a 8075+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
8076+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
8077+AuStubVoid(au_dbg_verify_kthread, void)
8078+AuStubInt0(__init au_debug_init, void)
1facf9fc 8079+
1facf9fc 8080+#define AuDbgWhlist(w) do {} while (0)
8081+#define AuDbgVdir(v) do {} while (0)
8082+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 8083+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 8084+#define AuDbgDentry(d) do {} while (0)
8085+#define AuDbgFile(f) do {} while (0)
8086+#define AuDbgSb(sb) do {} while (0)
4a4d8108 8087+#define AuDbgSym(addr) do {} while (0)
1facf9fc 8088+#endif /* CONFIG_AUFS_DEBUG */
8089+
8090+/* ---------------------------------------------------------------------- */
8091+
8092+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
8093+int __init au_sysrq_init(void);
8094+void au_sysrq_fin(void);
8095+
8096+#ifdef CONFIG_HW_CONSOLE
8097+#define au_dbg_blocked() do { \
8098+ WARN_ON(1); \
0c5527e5 8099+ handle_sysrq('w'); \
1facf9fc 8100+} while (0)
8101+#else
4a4d8108 8102+AuStubVoid(au_dbg_blocked, void)
1facf9fc 8103+#endif
8104+
8105+#else
4a4d8108
AM
8106+AuStubInt0(__init au_sysrq_init, void)
8107+AuStubVoid(au_sysrq_fin, void)
8108+AuStubVoid(au_dbg_blocked, void)
1facf9fc 8109+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
8110+
8111+#endif /* __KERNEL__ */
8112+#endif /* __AUFS_DEBUG_H__ */
7f207e10 8113diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
fbc438ed
JR
8114--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 08:00:00.000000000 +0800
8115+++ linux/fs/aufs/dentry.c 2019-07-11 21:21:54.379051070 +0800
eca801bf 8116@@ -0,0 +1,1154 @@
cd7a4cd9 8117+// SPDX-License-Identifier: GPL-2.0
1facf9fc 8118+/*
ba1aed25 8119+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 8120+ *
8121+ * This program, aufs is free software; you can redistribute it and/or modify
8122+ * it under the terms of the GNU General Public License as published by
8123+ * the Free Software Foundation; either version 2 of the License, or
8124+ * (at your option) any later version.
dece6358
AM
8125+ *
8126+ * This program is distributed in the hope that it will be useful,
8127+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8128+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8129+ * GNU General Public License for more details.
8130+ *
8131+ * You should have received a copy of the GNU General Public License
523b37e3 8132+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 8133+ */
8134+
8135+/*
8136+ * lookup and dentry operations
8137+ */
8138+
eca801bf 8139+#include <linux/iversion.h>
dece6358 8140+#include <linux/namei.h>
1facf9fc 8141+#include "aufs.h"
8142+
1facf9fc 8143+/*
8144+ * returns positive/negative dentry, NULL or an error.
8145+ * NULL means whiteout-ed or not-found.
8146+ */
8147+static struct dentry*
8148+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
8b6a4947 8149+ aufs_bindex_t bindex, struct au_do_lookup_args *args)
1facf9fc 8150+{
8151+ struct dentry *h_dentry;
2000de60 8152+ struct inode *h_inode;
1facf9fc 8153+ struct au_branch *br;
8154+ int wh_found, opq;
8155+ unsigned char wh_able;
8156+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
076b876e
AM
8157+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags,
8158+ IGNORE_PERM);
1facf9fc 8159+
1facf9fc 8160+ wh_found = 0;
8161+ br = au_sbr(dentry->d_sb, bindex);
8162+ wh_able = !!au_br_whable(br->br_perm);
8163+ if (wh_able)
8b6a4947 8164+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm);
1facf9fc 8165+ h_dentry = ERR_PTR(wh_found);
8166+ if (!wh_found)
8167+ goto real_lookup;
8168+ if (unlikely(wh_found < 0))
8169+ goto out;
8170+
8171+ /* We found a whiteout */
5afbbe0d 8172+ /* au_set_dbbot(dentry, bindex); */
1facf9fc 8173+ au_set_dbwh(dentry, bindex);
8174+ if (!allow_neg)
8175+ return NULL; /* success */
8176+
4f0767ce 8177+real_lookup:
076b876e 8178+ if (!ignore_perm)
8b6a4947 8179+ h_dentry = vfsub_lkup_one(args->name, h_parent);
076b876e 8180+ else
8b6a4947 8181+ h_dentry = au_sio_lkup_one(args->name, h_parent);
2000de60
JR
8182+ if (IS_ERR(h_dentry)) {
8183+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG
8184+ && !allow_neg)
8185+ h_dentry = NULL;
1facf9fc 8186+ goto out;
2000de60 8187+ }
1facf9fc 8188+
5527c038
JR
8189+ h_inode = d_inode(h_dentry);
8190+ if (d_is_negative(h_dentry)) {
1facf9fc 8191+ if (!allow_neg)
8192+ goto out_neg;
8193+ } else if (wh_found
8194+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
8195+ goto out_neg;
8b6a4947
AM
8196+ else if (au_ftest_lkup(args->flags, DIRREN)
8197+ /* && h_inode */
8198+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) {
8199+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry,
8200+ (unsigned long long)h_inode->i_ino);
8201+ goto out_neg;
8202+ }
1facf9fc 8203+
5afbbe0d
AM
8204+ if (au_dbbot(dentry) <= bindex)
8205+ au_set_dbbot(dentry, bindex);
8206+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
8207+ au_set_dbtop(dentry, bindex);
1facf9fc 8208+ au_set_h_dptr(dentry, bindex, h_dentry);
8209+
2000de60
JR
8210+ if (!d_is_dir(h_dentry)
8211+ || !wh_able
5527c038 8212+ || (d_really_is_positive(dentry) && !d_is_dir(dentry)))
1facf9fc 8213+ goto out; /* success */
8214+
be118d29 8215+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
076b876e 8216+ opq = au_diropq_test(h_dentry);
3c1bdaff 8217+ inode_unlock_shared(h_inode);
1facf9fc 8218+ if (opq > 0)
8219+ au_set_dbdiropq(dentry, bindex);
8220+ else if (unlikely(opq < 0)) {
8221+ au_set_h_dptr(dentry, bindex, NULL);
8222+ h_dentry = ERR_PTR(opq);
8223+ }
8224+ goto out;
8225+
4f0767ce 8226+out_neg:
1facf9fc 8227+ dput(h_dentry);
8228+ h_dentry = NULL;
4f0767ce 8229+out:
1facf9fc 8230+ return h_dentry;
8231+}
8232+
dece6358
AM
8233+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
8234+{
8235+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
8236+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
8237+ return -EPERM;
8238+ return 0;
8239+}
8240+
1facf9fc 8241+/*
8242+ * returns the number of lower positive dentries,
8243+ * otherwise an error.
8244+ * can be called at unlinking with @type is zero.
8245+ */
5afbbe0d
AM
8246+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
8247+ unsigned int flags)
1facf9fc 8248+{
8249+ int npositive, err;
8250+ aufs_bindex_t bindex, btail, bdiropq;
8b6a4947 8251+ unsigned char isdir, dirperm1, dirren;
1facf9fc 8252+ struct au_do_lookup_args args = {
8b6a4947
AM
8253+ .flags = flags,
8254+ .name = &dentry->d_name
1facf9fc 8255+ };
1facf9fc 8256+ struct dentry *parent;
076b876e 8257+ struct super_block *sb;
1facf9fc 8258+
076b876e 8259+ sb = dentry->d_sb;
8b6a4947 8260+ err = au_test_shwh(sb, args.name);
dece6358 8261+ if (unlikely(err))
1facf9fc 8262+ goto out;
8263+
8b6a4947 8264+ err = au_wh_name_alloc(&args.whname, args.name);
1facf9fc 8265+ if (unlikely(err))
8266+ goto out;
8267+
2000de60 8268+ isdir = !!d_is_dir(dentry);
076b876e 8269+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1);
8b6a4947
AM
8270+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
8271+ if (dirren)
8272+ au_fset_lkup(args.flags, DIRREN);
1facf9fc 8273+
8274+ npositive = 0;
4a4d8108 8275+ parent = dget_parent(dentry);
1facf9fc 8276+ btail = au_dbtaildir(parent);
5afbbe0d 8277+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8278+ struct dentry *h_parent, *h_dentry;
8279+ struct inode *h_inode, *h_dir;
8b6a4947 8280+ struct au_branch *br;
1facf9fc 8281+
8282+ h_dentry = au_h_dptr(dentry, bindex);
8283+ if (h_dentry) {
5527c038 8284+ if (d_is_positive(h_dentry))
1facf9fc 8285+ npositive++;
5afbbe0d 8286+ break;
1facf9fc 8287+ }
8288+ h_parent = au_h_dptr(parent, bindex);
2000de60 8289+ if (!h_parent || !d_is_dir(h_parent))
1facf9fc 8290+ continue;
8291+
8b6a4947
AM
8292+ if (dirren) {
8293+ /* if the inum matches, then use the prepared name */
8294+ err = au_dr_lkup_name(&args, bindex);
8295+ if (unlikely(err))
8296+ goto out_parent;
8297+ }
8298+
5527c038 8299+ h_dir = d_inode(h_parent);
be118d29 8300+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947 8301+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args);
3c1bdaff 8302+ inode_unlock_shared(h_dir);
1facf9fc 8303+ err = PTR_ERR(h_dentry);
8304+ if (IS_ERR(h_dentry))
4a4d8108 8305+ goto out_parent;
2000de60
JR
8306+ if (h_dentry)
8307+ au_fclr_lkup(args.flags, ALLOW_NEG);
076b876e
AM
8308+ if (dirperm1)
8309+ au_fset_lkup(args.flags, IGNORE_PERM);
1facf9fc 8310+
79b8bda9 8311+ if (au_dbwh(dentry) == bindex)
1facf9fc 8312+ break;
8313+ if (!h_dentry)
8314+ continue;
5527c038 8315+ if (d_is_negative(h_dentry))
1facf9fc 8316+ continue;
5527c038 8317+ h_inode = d_inode(h_dentry);
1facf9fc 8318+ npositive++;
8319+ if (!args.type)
8320+ args.type = h_inode->i_mode & S_IFMT;
8321+ if (args.type != S_IFDIR)
8322+ break;
8323+ else if (isdir) {
8324+ /* the type of lower may be different */
8325+ bdiropq = au_dbdiropq(dentry);
8326+ if (bdiropq >= 0 && bdiropq <= bindex)
8327+ break;
8328+ }
8b6a4947
AM
8329+ br = au_sbr(sb, bindex);
8330+ if (dirren
8331+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino,
8332+ /*add_ent*/NULL)) {
8333+ /* prepare next name to lookup */
8334+ err = au_dr_lkup(&args, dentry, bindex);
8335+ if (unlikely(err))
8336+ goto out_parent;
8337+ }
1facf9fc 8338+ }
8339+
8340+ if (npositive) {
8341+ AuLabel(positive);
5afbbe0d 8342+ au_update_dbtop(dentry);
1facf9fc 8343+ }
8344+ err = npositive;
076b876e 8345+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE)
5afbbe0d 8346+ && au_dbtop(dentry) < 0)) {
1facf9fc 8347+ err = -EIO;
523b37e3
AM
8348+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n",
8349+ dentry, err);
027c5e7a 8350+ }
1facf9fc 8351+
4f0767ce 8352+out_parent:
4a4d8108 8353+ dput(parent);
9f237c51 8354+ au_kfree_try_rcu(args.whname.name);
8b6a4947
AM
8355+ if (dirren)
8356+ au_dr_lkup_fin(&args);
4f0767ce 8357+out:
1facf9fc 8358+ return err;
8359+}
8360+
076b876e 8361+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent)
1facf9fc 8362+{
8363+ struct dentry *dentry;
8364+ int wkq_err;
8365+
5527c038 8366+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC))
b4510431 8367+ dentry = vfsub_lkup_one(name, parent);
1facf9fc 8368+ else {
b4510431
AM
8369+ struct vfsub_lkup_one_args args = {
8370+ .errp = &dentry,
8371+ .name = name,
8372+ .parent = parent
1facf9fc 8373+ };
8374+
b4510431 8375+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
1facf9fc 8376+ if (unlikely(wkq_err))
8377+ dentry = ERR_PTR(wkq_err);
8378+ }
8379+
8380+ return dentry;
8381+}
8382+
8383+/*
8384+ * lookup @dentry on @bindex which should be negative.
8385+ */
86dc4139 8386+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
1facf9fc 8387+{
8388+ int err;
8389+ struct dentry *parent, *h_parent, *h_dentry;
86dc4139 8390+ struct au_branch *br;
1facf9fc 8391+
1facf9fc 8392+ parent = dget_parent(dentry);
8393+ h_parent = au_h_dptr(parent, bindex);
86dc4139
AM
8394+ br = au_sbr(dentry->d_sb, bindex);
8395+ if (wh)
8396+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
8397+ else
076b876e 8398+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent);
1facf9fc 8399+ err = PTR_ERR(h_dentry);
8400+ if (IS_ERR(h_dentry))
8401+ goto out;
5527c038 8402+ if (unlikely(d_is_positive(h_dentry))) {
1facf9fc 8403+ err = -EIO;
523b37e3 8404+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex);
1facf9fc 8405+ dput(h_dentry);
8406+ goto out;
8407+ }
8408+
4a4d8108 8409+ err = 0;
5afbbe0d
AM
8410+ if (bindex < au_dbtop(dentry))
8411+ au_set_dbtop(dentry, bindex);
8412+ if (au_dbbot(dentry) < bindex)
8413+ au_set_dbbot(dentry, bindex);
1facf9fc 8414+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 8415+
4f0767ce 8416+out:
1facf9fc 8417+ dput(parent);
8418+ return err;
8419+}
8420+
8421+/* ---------------------------------------------------------------------- */
8422+
8423+/* subset of struct inode */
8424+struct au_iattr {
8425+ unsigned long i_ino;
8426+ /* unsigned int i_nlink; */
0c3ec466
AM
8427+ kuid_t i_uid;
8428+ kgid_t i_gid;
1facf9fc 8429+ u64 i_version;
8430+/*
8431+ loff_t i_size;
8432+ blkcnt_t i_blocks;
8433+*/
8434+ umode_t i_mode;
8435+};
8436+
8437+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
8438+{
8439+ ia->i_ino = h_inode->i_ino;
8440+ /* ia->i_nlink = h_inode->i_nlink; */
8441+ ia->i_uid = h_inode->i_uid;
8442+ ia->i_gid = h_inode->i_gid;
be118d29 8443+ ia->i_version = inode_query_iversion(h_inode);
1facf9fc 8444+/*
8445+ ia->i_size = h_inode->i_size;
8446+ ia->i_blocks = h_inode->i_blocks;
8447+*/
8448+ ia->i_mode = (h_inode->i_mode & S_IFMT);
8449+}
8450+
8451+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
8452+{
8453+ return ia->i_ino != h_inode->i_ino
8454+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466 8455+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 8456+ || !gid_eq(ia->i_gid, h_inode->i_gid)
be118d29 8457+ || !inode_eq_iversion(h_inode, ia->i_version)
1facf9fc 8458+/*
8459+ || ia->i_size != h_inode->i_size
8460+ || ia->i_blocks != h_inode->i_blocks
8461+*/
8462+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
8463+}
8464+
8465+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
8466+ struct au_branch *br)
8467+{
8468+ int err;
8469+ struct au_iattr ia;
8470+ struct inode *h_inode;
8471+ struct dentry *h_d;
8472+ struct super_block *h_sb;
8473+
8474+ err = 0;
8475+ memset(&ia, -1, sizeof(ia));
8476+ h_sb = h_dentry->d_sb;
5527c038
JR
8477+ h_inode = NULL;
8478+ if (d_is_positive(h_dentry)) {
8479+ h_inode = d_inode(h_dentry);
1facf9fc 8480+ au_iattr_save(&ia, h_inode);
5527c038 8481+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
1facf9fc 8482+ /* nfs d_revalidate may return 0 for negative dentry */
8483+ /* fuse d_revalidate always return 0 for negative dentry */
8484+ goto out;
8485+
8486+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
b4510431 8487+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
1facf9fc 8488+ err = PTR_ERR(h_d);
8489+ if (IS_ERR(h_d))
8490+ goto out;
8491+
8492+ err = 0;
8493+ if (unlikely(h_d != h_dentry
5527c038 8494+ || d_inode(h_d) != h_inode
1facf9fc 8495+ || (h_inode && au_iattr_test(&ia, h_inode))))
8496+ err = au_busy_or_stale();
8497+ dput(h_d);
8498+
4f0767ce 8499+out:
1facf9fc 8500+ AuTraceErr(err);
8501+ return err;
8502+}
8503+
8504+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
8505+ struct dentry *h_parent, struct au_branch *br)
8506+{
8507+ int err;
8508+
8509+ err = 0;
027c5e7a
AM
8510+ if (udba == AuOpt_UDBA_REVAL
8511+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 8512+ IMustLock(h_dir);
5527c038 8513+ err = (d_inode(h_dentry->d_parent) != h_dir);
027c5e7a 8514+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 8515+ err = au_h_verify_dentry(h_dentry, h_parent, br);
8516+
8517+ return err;
8518+}
8519+
8520+/* ---------------------------------------------------------------------- */
8521+
027c5e7a 8522+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 8523+{
027c5e7a 8524+ int err;
5afbbe0d 8525+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq;
027c5e7a
AM
8526+ struct au_hdentry tmp, *p, *q;
8527+ struct au_dinfo *dinfo;
8528+ struct super_block *sb;
1facf9fc 8529+
027c5e7a 8530+ DiMustWriteLock(dentry);
1308ab2a 8531+
027c5e7a
AM
8532+ sb = dentry->d_sb;
8533+ dinfo = au_di(dentry);
5afbbe0d 8534+ bbot = dinfo->di_bbot;
1facf9fc 8535+ bwh = dinfo->di_bwh;
8536+ bdiropq = dinfo->di_bdiropq;
5afbbe0d
AM
8537+ bindex = dinfo->di_btop;
8538+ p = au_hdentry(dinfo, bindex);
8539+ for (; bindex <= bbot; bindex++, p++) {
027c5e7a 8540+ if (!p->hd_dentry)
1facf9fc 8541+ continue;
8542+
027c5e7a
AM
8543+ new_bindex = au_br_index(sb, p->hd_id);
8544+ if (new_bindex == bindex)
1facf9fc 8545+ continue;
1facf9fc 8546+
1facf9fc 8547+ if (dinfo->di_bwh == bindex)
8548+ bwh = new_bindex;
8549+ if (dinfo->di_bdiropq == bindex)
8550+ bdiropq = new_bindex;
8551+ if (new_bindex < 0) {
8552+ au_hdput(p);
8553+ p->hd_dentry = NULL;
8554+ continue;
8555+ }
8556+
8557+ /* swap two lower dentries, and loop again */
5afbbe0d 8558+ q = au_hdentry(dinfo, new_bindex);
1facf9fc 8559+ tmp = *q;
8560+ *q = *p;
8561+ *p = tmp;
8562+ if (tmp.hd_dentry) {
8563+ bindex--;
8564+ p--;
8565+ }
8566+ }
8567+
1facf9fc 8568+ dinfo->di_bwh = -1;
5afbbe0d 8569+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh))
1facf9fc 8570+ dinfo->di_bwh = bwh;
8571+
8572+ dinfo->di_bdiropq = -1;
8573+ if (bdiropq >= 0
5afbbe0d 8574+ && bdiropq <= au_sbbot(sb)
1facf9fc 8575+ && au_sbr_whable(sb, bdiropq))
8576+ dinfo->di_bdiropq = bdiropq;
8577+
027c5e7a 8578+ err = -EIO;
5afbbe0d
AM
8579+ dinfo->di_btop = -1;
8580+ dinfo->di_bbot = -1;
8581+ bbot = au_dbbot(parent);
8582+ bindex = 0;
8583+ p = au_hdentry(dinfo, bindex);
8584+ for (; bindex <= bbot; bindex++, p++)
1facf9fc 8585+ if (p->hd_dentry) {
5afbbe0d 8586+ dinfo->di_btop = bindex;
1facf9fc 8587+ break;
8588+ }
8589+
5afbbe0d
AM
8590+ if (dinfo->di_btop >= 0) {
8591+ bindex = bbot;
8592+ p = au_hdentry(dinfo, bindex);
8593+ for (; bindex >= 0; bindex--, p--)
027c5e7a 8594+ if (p->hd_dentry) {
5afbbe0d 8595+ dinfo->di_bbot = bindex;
027c5e7a
AM
8596+ err = 0;
8597+ break;
8598+ }
8599+ }
8600+
8601+ return err;
1facf9fc 8602+}
8603+
027c5e7a 8604+static void au_do_hide(struct dentry *dentry)
1facf9fc 8605+{
027c5e7a 8606+ struct inode *inode;
1facf9fc 8607+
5527c038
JR
8608+ if (d_really_is_positive(dentry)) {
8609+ inode = d_inode(dentry);
8610+ if (!d_is_dir(dentry)) {
027c5e7a
AM
8611+ if (inode->i_nlink && !d_unhashed(dentry))
8612+ drop_nlink(inode);
8613+ } else {
8614+ clear_nlink(inode);
8615+ /* stop next lookup */
8616+ inode->i_flags |= S_DEAD;
8617+ }
8618+ smp_mb(); /* necessary? */
8619+ }
8620+ d_drop(dentry);
8621+}
1308ab2a 8622+
027c5e7a
AM
8623+static int au_hide_children(struct dentry *parent)
8624+{
8625+ int err, i, j, ndentry;
8626+ struct au_dcsub_pages dpages;
8627+ struct au_dpage *dpage;
8628+ struct dentry *dentry;
1facf9fc 8629+
027c5e7a 8630+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 8631+ if (unlikely(err))
8632+ goto out;
027c5e7a
AM
8633+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
8634+ if (unlikely(err))
8635+ goto out_dpages;
1facf9fc 8636+
027c5e7a
AM
8637+ /* in reverse order */
8638+ for (i = dpages.ndpage - 1; i >= 0; i--) {
8639+ dpage = dpages.dpages + i;
8640+ ndentry = dpage->ndentry;
8641+ for (j = ndentry - 1; j >= 0; j--) {
8642+ dentry = dpage->dentries[j];
8643+ if (dentry != parent)
8644+ au_do_hide(dentry);
8645+ }
8646+ }
1facf9fc 8647+
027c5e7a
AM
8648+out_dpages:
8649+ au_dpages_free(&dpages);
4f0767ce 8650+out:
027c5e7a 8651+ return err;
1facf9fc 8652+}
8653+
027c5e7a 8654+static void au_hide(struct dentry *dentry)
1facf9fc 8655+{
027c5e7a 8656+ int err;
1facf9fc 8657+
027c5e7a 8658+ AuDbgDentry(dentry);
2000de60 8659+ if (d_is_dir(dentry)) {
027c5e7a
AM
8660+ /* shrink_dcache_parent(dentry); */
8661+ err = au_hide_children(dentry);
8662+ if (unlikely(err))
523b37e3
AM
8663+ AuIOErr("%pd, failed hiding children, ignored %d\n",
8664+ dentry, err);
027c5e7a
AM
8665+ }
8666+ au_do_hide(dentry);
8667+}
1facf9fc 8668+
027c5e7a
AM
8669+/*
8670+ * By adding a dirty branch, a cached dentry may be affected in various ways.
8671+ *
8672+ * a dirty branch is added
8673+ * - on the top of layers
8674+ * - in the middle of layers
8675+ * - to the bottom of layers
8676+ *
8677+ * on the added branch there exists
8678+ * - a whiteout
8679+ * - a diropq
8680+ * - a same named entry
8681+ * + exist
8682+ * * negative --> positive
8683+ * * positive --> positive
8684+ * - type is unchanged
8685+ * - type is changed
8686+ * + doesn't exist
8687+ * * negative --> negative
8688+ * * positive --> negative (rejected by au_br_del() for non-dir case)
8689+ * - none
8690+ */
8691+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
8692+ struct au_dinfo *tmp)
8693+{
8694+ int err;
5afbbe0d 8695+ aufs_bindex_t bindex, bbot;
027c5e7a
AM
8696+ struct {
8697+ struct dentry *dentry;
8698+ struct inode *inode;
8699+ mode_t mode;
be52b249
AM
8700+ } orig_h, tmp_h = {
8701+ .dentry = NULL
8702+ };
027c5e7a
AM
8703+ struct au_hdentry *hd;
8704+ struct inode *inode, *h_inode;
8705+ struct dentry *h_dentry;
8706+
8707+ err = 0;
5afbbe0d 8708+ AuDebugOn(dinfo->di_btop < 0);
027c5e7a 8709+ orig_h.mode = 0;
5afbbe0d 8710+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry;
5527c038
JR
8711+ orig_h.inode = NULL;
8712+ if (d_is_positive(orig_h.dentry)) {
8713+ orig_h.inode = d_inode(orig_h.dentry);
027c5e7a 8714+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5527c038 8715+ }
5afbbe0d
AM
8716+ if (tmp->di_btop >= 0) {
8717+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry;
5527c038
JR
8718+ if (d_is_positive(tmp_h.dentry)) {
8719+ tmp_h.inode = d_inode(tmp_h.dentry);
027c5e7a 8720+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5527c038 8721+ }
027c5e7a
AM
8722+ }
8723+
5527c038
JR
8724+ inode = NULL;
8725+ if (d_really_is_positive(dentry))
8726+ inode = d_inode(dentry);
027c5e7a 8727+ if (!orig_h.inode) {
acd2b654 8728+ AuDbg("negative originally\n");
027c5e7a
AM
8729+ if (inode) {
8730+ au_hide(dentry);
8731+ goto out;
8732+ }
8733+ AuDebugOn(inode);
5afbbe0d 8734+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
027c5e7a
AM
8735+ AuDebugOn(dinfo->di_bdiropq != -1);
8736+
8737+ if (!tmp_h.inode) {
8738+ AuDbg("negative --> negative\n");
8739+ /* should have only one negative lower */
5afbbe0d
AM
8740+ if (tmp->di_btop >= 0
8741+ && tmp->di_btop < dinfo->di_btop) {
8742+ AuDebugOn(tmp->di_btop != tmp->di_bbot);
8743+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
8744+ au_set_h_dptr(dentry, dinfo->di_btop, NULL);
027c5e7a 8745+ au_di_cp(dinfo, tmp);
5afbbe0d
AM
8746+ hd = au_hdentry(tmp, tmp->di_btop);
8747+ au_set_h_dptr(dentry, tmp->di_btop,
027c5e7a
AM
8748+ dget(hd->hd_dentry));
8749+ }
8750+ au_dbg_verify_dinode(dentry);
8751+ } else {
8752+ AuDbg("negative --> positive\n");
8753+ /*
8754+ * similar to the behaviour of creating with bypassing
8755+ * aufs.
8756+ * unhash it in order to force an error in the
8757+ * succeeding create operation.
8758+ * we should not set S_DEAD here.
8759+ */
8760+ d_drop(dentry);
8761+ /* au_di_swap(tmp, dinfo); */
8762+ au_dbg_verify_dinode(dentry);
8763+ }
8764+ } else {
8765+ AuDbg("positive originally\n");
8766+ /* inode may be NULL */
8767+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
8768+ if (!tmp_h.inode) {
8769+ AuDbg("positive --> negative\n");
8770+ /* or bypassing aufs */
8771+ au_hide(dentry);
5afbbe0d 8772+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop)
027c5e7a
AM
8773+ dinfo->di_bwh = tmp->di_bwh;
8774+ if (inode)
8775+ err = au_refresh_hinode_self(inode);
8776+ au_dbg_verify_dinode(dentry);
8777+ } else if (orig_h.mode == tmp_h.mode) {
8778+ AuDbg("positive --> positive, same type\n");
8779+ if (!S_ISDIR(orig_h.mode)
5afbbe0d 8780+ && dinfo->di_btop > tmp->di_btop) {
027c5e7a
AM
8781+ /*
8782+ * similar to the behaviour of removing and
8783+ * creating.
8784+ */
8785+ au_hide(dentry);
8786+ if (inode)
8787+ err = au_refresh_hinode_self(inode);
8788+ au_dbg_verify_dinode(dentry);
8789+ } else {
8790+ /* fill empty slots */
5afbbe0d
AM
8791+ if (dinfo->di_btop > tmp->di_btop)
8792+ dinfo->di_btop = tmp->di_btop;
8793+ if (dinfo->di_bbot < tmp->di_bbot)
8794+ dinfo->di_bbot = tmp->di_bbot;
027c5e7a
AM
8795+ dinfo->di_bwh = tmp->di_bwh;
8796+ dinfo->di_bdiropq = tmp->di_bdiropq;
5afbbe0d
AM
8797+ bbot = dinfo->di_bbot;
8798+ bindex = tmp->di_btop;
8799+ hd = au_hdentry(tmp, bindex);
8800+ for (; bindex <= bbot; bindex++, hd++) {
027c5e7a
AM
8801+ if (au_h_dptr(dentry, bindex))
8802+ continue;
5afbbe0d 8803+ h_dentry = hd->hd_dentry;
027c5e7a
AM
8804+ if (!h_dentry)
8805+ continue;
5527c038
JR
8806+ AuDebugOn(d_is_negative(h_dentry));
8807+ h_inode = d_inode(h_dentry);
027c5e7a
AM
8808+ AuDebugOn(orig_h.mode
8809+ != (h_inode->i_mode
8810+ & S_IFMT));
8811+ au_set_h_dptr(dentry, bindex,
8812+ dget(h_dentry));
8813+ }
5afbbe0d
AM
8814+ if (inode)
8815+ err = au_refresh_hinode(inode, dentry);
027c5e7a
AM
8816+ au_dbg_verify_dinode(dentry);
8817+ }
8818+ } else {
8819+ AuDbg("positive --> positive, different type\n");
8820+ /* similar to the behaviour of removing and creating */
8821+ au_hide(dentry);
8822+ if (inode)
8823+ err = au_refresh_hinode_self(inode);
8824+ au_dbg_verify_dinode(dentry);
8825+ }
8826+ }
8827+
8828+out:
8829+ return err;
8830+}
8831+
79b8bda9
AM
8832+void au_refresh_dop(struct dentry *dentry, int force_reval)
8833+{
8834+ const struct dentry_operations *dop
8835+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op;
8836+ static const unsigned int mask
8837+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE;
8838+
8839+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags));
8840+
8841+ if (dentry->d_op == dop)
8842+ return;
8843+
8844+ AuDbg("%pd\n", dentry);
8845+ spin_lock(&dentry->d_lock);
8846+ if (dop == &aufs_dop)
8847+ dentry->d_flags |= mask;
8848+ else
8849+ dentry->d_flags &= ~mask;
8850+ dentry->d_op = dop;
8851+ spin_unlock(&dentry->d_lock);
8852+}
8853+
027c5e7a
AM
8854+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
8855+{
e2f27e51 8856+ int err, ebrange, nbr;
027c5e7a
AM
8857+ unsigned int sigen;
8858+ struct au_dinfo *dinfo, *tmp;
8859+ struct super_block *sb;
8860+ struct inode *inode;
8861+
8862+ DiMustWriteLock(dentry);
8863+ AuDebugOn(IS_ROOT(dentry));
5527c038 8864+ AuDebugOn(d_really_is_negative(parent));
027c5e7a
AM
8865+
8866+ sb = dentry->d_sb;
027c5e7a
AM
8867+ sigen = au_sigen(sb);
8868+ err = au_digen_test(parent, sigen);
8869+ if (unlikely(err))
8870+ goto out;
8871+
e2f27e51 8872+ nbr = au_sbbot(sb) + 1;
027c5e7a 8873+ dinfo = au_di(dentry);
e2f27e51 8874+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0);
027c5e7a
AM
8875+ if (unlikely(err))
8876+ goto out;
8877+ ebrange = au_dbrange_test(dentry);
8878+ if (!ebrange)
8879+ ebrange = au_do_refresh_hdentry(dentry, parent);
8880+
38d290e6 8881+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) {
5afbbe0d 8882+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0);
5527c038
JR
8883+ if (d_really_is_positive(dentry)) {
8884+ inode = d_inode(dentry);
027c5e7a 8885+ err = au_refresh_hinode_self(inode);
5527c038 8886+ }
027c5e7a
AM
8887+ au_dbg_verify_dinode(dentry);
8888+ if (!err)
8889+ goto out_dgen; /* success */
8890+ goto out;
8891+ }
8892+
8893+ /* temporary dinfo */
8894+ AuDbgDentry(dentry);
8895+ err = -ENOMEM;
8896+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
8897+ if (unlikely(!tmp))
8898+ goto out;
8899+ au_di_swap(tmp, dinfo);
8900+ /* returns the number of positive dentries */
8901+ /*
8902+ * if current working dir is removed, it returns an error.
8903+ * but the dentry is legal.
8904+ */
5afbbe0d 8905+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
027c5e7a
AM
8906+ AuDbgDentry(dentry);
8907+ au_di_swap(tmp, dinfo);
8908+ if (err == -ENOENT)
8909+ err = 0;
8910+ if (err >= 0) {
8911+ /* compare/refresh by dinfo */
8912+ AuDbgDentry(dentry);
8913+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
8914+ au_dbg_verify_dinode(dentry);
8915+ AuTraceErr(err);
8916+ }
e2f27e51 8917+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */
027c5e7a
AM
8918+ au_rw_write_unlock(&tmp->di_rwsem);
8919+ au_di_free(tmp);
8920+ if (unlikely(err))
8921+ goto out;
8922+
8923+out_dgen:
8924+ au_update_digen(dentry);
8925+out:
8926+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
523b37e3 8927+ AuIOErr("failed refreshing %pd, %d\n", dentry, err);
027c5e7a
AM
8928+ AuDbgDentry(dentry);
8929+ }
8930+ AuTraceErr(err);
8931+ return err;
8932+}
8933+
b4510431
AM
8934+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
8935+ struct dentry *dentry, aufs_bindex_t bindex)
027c5e7a
AM
8936+{
8937+ int err, valid;
027c5e7a
AM
8938+
8939+ err = 0;
8940+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
8941+ goto out;
027c5e7a
AM
8942+
8943+ AuDbg("b%d\n", bindex);
b4510431
AM
8944+ /*
8945+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
8946+ * due to whiteout and branch permission.
8947+ */
8948+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
8949+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
8950+ /* it may return tri-state */
8951+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags);
1facf9fc 8952+
8953+ if (unlikely(valid < 0))
8954+ err = valid;
8955+ else if (!valid)
8956+ err = -EINVAL;
8957+
4f0767ce 8958+out:
1facf9fc 8959+ AuTraceErr(err);
8960+ return err;
8961+}
8962+
8963+/* todo: remove this */
8964+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
8b6a4947 8965+ unsigned int flags, int do_udba, int dirren)
1facf9fc 8966+{
8967+ int err;
8968+ umode_t mode, h_mode;
5afbbe0d 8969+ aufs_bindex_t bindex, btail, btop, ibs, ibe;
38d290e6 8970+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile;
4a4d8108 8971+ struct inode *h_inode, *h_cached_inode;
1facf9fc 8972+ struct dentry *h_dentry;
8973+ struct qstr *name, *h_name;
8974+
8975+ err = 0;
8976+ plus = 0;
8977+ mode = 0;
1facf9fc 8978+ ibs = -1;
8979+ ibe = -1;
8980+ unhashed = !!d_unhashed(dentry);
8981+ is_root = !!IS_ROOT(dentry);
8982+ name = &dentry->d_name;
38d290e6 8983+ tmpfile = au_di(dentry)->di_tmpfile;
1facf9fc 8984+
8985+ /*
7f207e10
AM
8986+ * Theoretically, REVAL test should be unnecessary in case of
8987+ * {FS,I}NOTIFY.
8988+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 8989+ * IN_ATTRIB for atime/nlink/pageio
1facf9fc 8990+ * Let's do REVAL test too.
8991+ */
8992+ if (do_udba && inode) {
8993+ mode = (inode->i_mode & S_IFMT);
8994+ plus = (inode->i_nlink > 0);
5afbbe0d
AM
8995+ ibs = au_ibtop(inode);
8996+ ibe = au_ibbot(inode);
1facf9fc 8997+ }
8998+
5afbbe0d
AM
8999+ btop = au_dbtop(dentry);
9000+ btail = btop;
1facf9fc 9001+ if (inode && S_ISDIR(inode->i_mode))
9002+ btail = au_dbtaildir(dentry);
5afbbe0d 9003+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 9004+ h_dentry = au_h_dptr(dentry, bindex);
9005+ if (!h_dentry)
9006+ continue;
9007+
523b37e3
AM
9008+ AuDbg("b%d, %pd\n", bindex, h_dentry);
9009+ h_nfs = !!au_test_nfs(h_dentry->d_sb);
027c5e7a 9010+ spin_lock(&h_dentry->d_lock);
1facf9fc 9011+ h_name = &h_dentry->d_name;
9012+ if (unlikely(do_udba
9013+ && !is_root
523b37e3
AM
9014+ && ((!h_nfs
9015+ && (unhashed != !!d_unhashed(h_dentry)
8b6a4947 9016+ || (!tmpfile && !dirren
38d290e6
JR
9017+ && !au_qstreq(name, h_name))
9018+ ))
523b37e3
AM
9019+ || (h_nfs
9020+ && !(flags & LOOKUP_OPEN)
9021+ && (h_dentry->d_flags
9022+ & DCACHE_NFSFS_RENAMED)))
1facf9fc 9023+ )) {
38d290e6
JR
9024+ int h_unhashed;
9025+
9026+ h_unhashed = d_unhashed(h_dentry);
027c5e7a 9027+ spin_unlock(&h_dentry->d_lock);
38d290e6
JR
9028+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n",
9029+ unhashed, h_unhashed, dentry, h_dentry);
1facf9fc 9030+ goto err;
9031+ }
027c5e7a 9032+ spin_unlock(&h_dentry->d_lock);
1facf9fc 9033+
b4510431 9034+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex);
1facf9fc 9035+ if (unlikely(err))
9036+ /* do not goto err, to keep the errno */
9037+ break;
9038+
9039+ /* todo: plink too? */
9040+ if (!do_udba)
9041+ continue;
9042+
9043+ /* UDBA tests */
5527c038 9044+ if (unlikely(!!inode != d_is_positive(h_dentry)))
1facf9fc 9045+ goto err;
9046+
5527c038
JR
9047+ h_inode = NULL;
9048+ if (d_is_positive(h_dentry))
9049+ h_inode = d_inode(h_dentry);
1facf9fc 9050+ h_plus = plus;
9051+ h_mode = mode;
9052+ h_cached_inode = h_inode;
9053+ if (h_inode) {
9054+ h_mode = (h_inode->i_mode & S_IFMT);
9055+ h_plus = (h_inode->i_nlink > 0);
9056+ }
9057+ if (inode && ibs <= bindex && bindex <= ibe)
9058+ h_cached_inode = au_h_iptr(inode, bindex);
9059+
523b37e3 9060+ if (!h_nfs) {
38d290e6 9061+ if (unlikely(plus != h_plus && !tmpfile))
523b37e3
AM
9062+ goto err;
9063+ } else {
9064+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED)
9065+ && !is_root
9066+ && !IS_ROOT(h_dentry)
9067+ && unhashed != d_unhashed(h_dentry)))
9068+ goto err;
9069+ }
9070+ if (unlikely(mode != h_mode
1facf9fc 9071+ || h_cached_inode != h_inode))
9072+ goto err;
9073+ continue;
9074+
f6b6e03d 9075+err:
1facf9fc 9076+ err = -EINVAL;
9077+ break;
9078+ }
9079+
523b37e3 9080+ AuTraceErr(err);
1facf9fc 9081+ return err;
9082+}
9083+
027c5e7a 9084+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 9085+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
9086+{
9087+ int err;
9088+ struct dentry *parent;
1facf9fc 9089+
027c5e7a 9090+ if (!au_digen_test(dentry, sigen))
1facf9fc 9091+ return 0;
9092+
9093+ parent = dget_parent(dentry);
9094+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 9095+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 9096+ au_dbg_verify_gen(parent, sigen);
027c5e7a 9097+ err = au_refresh_dentry(dentry, parent);
1facf9fc 9098+ di_read_unlock(parent, AuLock_IR);
9099+ dput(parent);
027c5e7a 9100+ AuTraceErr(err);
1facf9fc 9101+ return err;
9102+}
9103+
9104+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
9105+{
9106+ int err;
9107+ struct dentry *d, *parent;
1facf9fc 9108+
027c5e7a 9109+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 9110+ return simple_reval_dpath(dentry, sigen);
9111+
9112+ /* slow loop, keep it simple and stupid */
9113+ /* cf: au_cpup_dirs() */
9114+ err = 0;
9115+ parent = NULL;
027c5e7a 9116+ while (au_digen_test(dentry, sigen)) {
1facf9fc 9117+ d = dentry;
9118+ while (1) {
9119+ dput(parent);
9120+ parent = dget_parent(d);
027c5e7a 9121+ if (!au_digen_test(parent, sigen))
1facf9fc 9122+ break;
9123+ d = parent;
9124+ }
9125+
1facf9fc 9126+ if (d != dentry)
027c5e7a 9127+ di_write_lock_child2(d);
1facf9fc 9128+
9129+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
9130+ if (au_digen_test(d, sigen)) {
9131+ /*
9132+ * todo: consolidate with simple_reval_dpath(),
9133+ * do_refresh() and au_reval_for_attr().
9134+ */
1facf9fc 9135+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 9136+ err = au_refresh_dentry(d, parent);
1facf9fc 9137+ di_read_unlock(parent, AuLock_IR);
9138+ }
9139+
9140+ if (d != dentry)
9141+ di_write_unlock(d);
9142+ dput(parent);
9143+ if (unlikely(err))
9144+ break;
9145+ }
9146+
9147+ return err;
9148+}
9149+
9150+/*
9151+ * if valid returns 1, otherwise 0.
9152+ */
b4510431 9153+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags)
1facf9fc 9154+{
9155+ int valid, err;
9156+ unsigned int sigen;
8b6a4947 9157+ unsigned char do_udba, dirren;
1facf9fc 9158+ struct super_block *sb;
9159+ struct inode *inode;
9160+
027c5e7a 9161+ /* todo: support rcu-walk? */
b4510431 9162+ if (flags & LOOKUP_RCU)
027c5e7a
AM
9163+ return -ECHILD;
9164+
9165+ valid = 0;
9166+ if (unlikely(!au_di(dentry)))
9167+ goto out;
9168+
e49829fe 9169+ valid = 1;
1facf9fc 9170+ sb = dentry->d_sb;
e49829fe
JR
9171+ /*
9172+ * todo: very ugly
9173+ * i_mutex of parent dir may be held,
9174+ * but we should not return 'invalid' due to busy.
9175+ */
9176+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
9177+ if (unlikely(err)) {
9178+ valid = err;
027c5e7a 9179+ AuTraceErr(err);
e49829fe
JR
9180+ goto out;
9181+ }
5527c038
JR
9182+ inode = NULL;
9183+ if (d_really_is_positive(dentry))
9184+ inode = d_inode(dentry);
5afbbe0d 9185+ if (unlikely(inode && au_is_bad_inode(inode))) {
c1595e42
JR
9186+ err = -EINVAL;
9187+ AuTraceErr(err);
9188+ goto out_dgrade;
9189+ }
027c5e7a
AM
9190+ if (unlikely(au_dbrange_test(dentry))) {
9191+ err = -EINVAL;
9192+ AuTraceErr(err);
9193+ goto out_dgrade;
1facf9fc 9194+ }
027c5e7a
AM
9195+
9196+ sigen = au_sigen(sb);
9197+ if (au_digen_test(dentry, sigen)) {
1facf9fc 9198+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
9199+ err = au_reval_dpath(dentry, sigen);
9200+ if (unlikely(err)) {
9201+ AuTraceErr(err);
1facf9fc 9202+ goto out_dgrade;
027c5e7a 9203+ }
1facf9fc 9204+ }
9205+ di_downgrade_lock(dentry, AuLock_IR);
9206+
1facf9fc 9207+ err = -EINVAL;
c1595e42 9208+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY))
523b37e3 9209+ && inode
38d290e6 9210+ && !(inode->i_state && I_LINKABLE)
79b8bda9
AM
9211+ && (IS_DEADDIR(inode) || !inode->i_nlink)) {
9212+ AuTraceErr(err);
027c5e7a 9213+ goto out_inval;
79b8bda9 9214+ }
027c5e7a 9215+
1facf9fc 9216+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
9217+ if (do_udba && inode) {
5afbbe0d 9218+ aufs_bindex_t btop = au_ibtop(inode);
027c5e7a 9219+ struct inode *h_inode;
1facf9fc 9220+
5afbbe0d
AM
9221+ if (btop >= 0) {
9222+ h_inode = au_h_iptr(inode, btop);
79b8bda9
AM
9223+ if (h_inode && au_test_higen(inode, h_inode)) {
9224+ AuTraceErr(err);
027c5e7a 9225+ goto out_inval;
79b8bda9 9226+ }
027c5e7a 9227+ }
1facf9fc 9228+ }
9229+
8b6a4947
AM
9230+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
9231+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren);
5afbbe0d 9232+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) {
1facf9fc 9233+ err = -EIO;
523b37e3
AM
9234+ AuDbg("both of real entry and whiteout found, %p, err %d\n",
9235+ dentry, err);
027c5e7a 9236+ }
e49829fe 9237+ goto out_inval;
1facf9fc 9238+
4f0767ce 9239+out_dgrade:
1facf9fc 9240+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 9241+out_inval:
1facf9fc 9242+ aufs_read_unlock(dentry, AuLock_IR);
9243+ AuTraceErr(err);
9244+ valid = !err;
e49829fe 9245+out:
027c5e7a 9246+ if (!valid) {
523b37e3 9247+ AuDbg("%pd invalid, %d\n", dentry, valid);
027c5e7a
AM
9248+ d_drop(dentry);
9249+ }
1facf9fc 9250+ return valid;
9251+}
9252+
9253+static void aufs_d_release(struct dentry *dentry)
9254+{
027c5e7a 9255+ if (au_di(dentry)) {
4a4d8108
AM
9256+ au_di_fin(dentry);
9257+ au_hn_di_reinit(dentry);
1facf9fc 9258+ }
1facf9fc 9259+}
9260+
4a4d8108 9261+const struct dentry_operations aufs_dop = {
c06a8ce3
AM
9262+ .d_revalidate = aufs_d_revalidate,
9263+ .d_weak_revalidate = aufs_d_revalidate,
9264+ .d_release = aufs_d_release
1facf9fc 9265+};
79b8bda9
AM
9266+
9267+/* aufs_dop without d_revalidate */
9268+const struct dentry_operations aufs_dop_noreval = {
9269+ .d_release = aufs_d_release
9270+};
7f207e10 9271diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
fbc438ed
JR
9272--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 08:00:00.000000000 +0800
9273+++ linux/fs/aufs/dentry.h 2019-07-11 21:21:54.379051070 +0800
9f237c51 9274@@ -0,0 +1,268 @@
062440b3 9275+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 9276+/*
ba1aed25 9277+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 9278+ *
9279+ * This program, aufs is free software; you can redistribute it and/or modify
9280+ * it under the terms of the GNU General Public License as published by
9281+ * the Free Software Foundation; either version 2 of the License, or
9282+ * (at your option) any later version.
dece6358
AM
9283+ *
9284+ * This program is distributed in the hope that it will be useful,
9285+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9286+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9287+ * GNU General Public License for more details.
9288+ *
9289+ * You should have received a copy of the GNU General Public License
523b37e3 9290+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9291+ */
9292+
9293+/*
9294+ * lookup and dentry operations
9295+ */
9296+
9297+#ifndef __AUFS_DENTRY_H__
9298+#define __AUFS_DENTRY_H__
9299+
9300+#ifdef __KERNEL__
9301+
dece6358 9302+#include <linux/dcache.h>
8b6a4947 9303+#include "dirren.h"
1facf9fc 9304+#include "rwsem.h"
9305+
1facf9fc 9306+struct au_hdentry {
9307+ struct dentry *hd_dentry;
027c5e7a 9308+ aufs_bindex_t hd_id;
1facf9fc 9309+};
9310+
9311+struct au_dinfo {
9312+ atomic_t di_generation;
9313+
dece6358 9314+ struct au_rwsem di_rwsem;
5afbbe0d 9315+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq;
38d290e6 9316+ unsigned char di_tmpfile; /* to allow the different name */
1c60b727 9317+ struct au_hdentry *di_hdentry;
9f237c51 9318+ struct rcu_head rcu;
4a4d8108 9319+} ____cacheline_aligned_in_smp;
1facf9fc 9320+
9321+/* ---------------------------------------------------------------------- */
9322+
5afbbe0d
AM
9323+/* flags for au_lkup_dentry() */
9324+#define AuLkup_ALLOW_NEG 1
9325+#define AuLkup_IGNORE_PERM (1 << 1)
8b6a4947 9326+#define AuLkup_DIRREN (1 << 2)
5afbbe0d
AM
9327+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
9328+#define au_fset_lkup(flags, name) \
9329+ do { (flags) |= AuLkup_##name; } while (0)
9330+#define au_fclr_lkup(flags, name) \
9331+ do { (flags) &= ~AuLkup_##name; } while (0)
9332+
8b6a4947
AM
9333+#ifndef CONFIG_AUFS_DIRREN
9334+#undef AuLkup_DIRREN
9335+#define AuLkup_DIRREN 0
9336+#endif
9337+
9338+struct au_do_lookup_args {
9339+ unsigned int flags;
9340+ mode_t type;
9341+ struct qstr whname, *name;
9342+ struct au_dr_lookup dirren;
9343+};
9344+
5afbbe0d
AM
9345+/* ---------------------------------------------------------------------- */
9346+
1facf9fc 9347+/* dentry.c */
79b8bda9 9348+extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
1facf9fc 9349+struct au_branch;
076b876e 9350+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
1facf9fc 9351+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
9352+ struct dentry *h_parent, struct au_branch *br);
9353+
5afbbe0d
AM
9354+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
9355+ unsigned int flags);
86dc4139 9356+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
027c5e7a 9357+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 9358+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
79b8bda9 9359+void au_refresh_dop(struct dentry *dentry, int force_reval);
1facf9fc 9360+
9361+/* dinfo.c */
4a4d8108 9362+void au_di_init_once(void *_di);
027c5e7a
AM
9363+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
9364+void au_di_free(struct au_dinfo *dinfo);
9365+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
9366+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
9367+int au_di_init(struct dentry *dentry);
9368+void au_di_fin(struct dentry *dentry);
e2f27e51 9369+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink);
1facf9fc 9370+
9371+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
9372+void di_read_unlock(struct dentry *d, int flags);
9373+void di_downgrade_lock(struct dentry *d, int flags);
9374+void di_write_lock(struct dentry *d, unsigned int lsc);
9375+void di_write_unlock(struct dentry *d);
9376+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
9377+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
9378+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
9379+
9380+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 9381+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 9382+aufs_bindex_t au_dbtail(struct dentry *dentry);
9383+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
9384+
9385+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9386+ struct dentry *h_dentry);
027c5e7a
AM
9387+int au_digen_test(struct dentry *dentry, unsigned int sigen);
9388+int au_dbrange_test(struct dentry *dentry);
1facf9fc 9389+void au_update_digen(struct dentry *dentry);
9390+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5afbbe0d
AM
9391+void au_update_dbtop(struct dentry *dentry);
9392+void au_update_dbbot(struct dentry *dentry);
1facf9fc 9393+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
9394+
9395+/* ---------------------------------------------------------------------- */
9396+
9397+static inline struct au_dinfo *au_di(struct dentry *dentry)
9398+{
9399+ return dentry->d_fsdata;
9400+}
9401+
9402+/* ---------------------------------------------------------------------- */
9403+
9404+/* lock subclass for dinfo */
9405+enum {
9406+ AuLsc_DI_CHILD, /* child first */
4a4d8108 9407+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 9408+ AuLsc_DI_CHILD3, /* copyup dirs */
9409+ AuLsc_DI_PARENT,
9410+ AuLsc_DI_PARENT2,
027c5e7a
AM
9411+ AuLsc_DI_PARENT3,
9412+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 9413+};
9414+
9415+/*
9416+ * di_read_lock_child, di_write_lock_child,
9417+ * di_read_lock_child2, di_write_lock_child2,
9418+ * di_read_lock_child3, di_write_lock_child3,
9419+ * di_read_lock_parent, di_write_lock_parent,
9420+ * di_read_lock_parent2, di_write_lock_parent2,
9421+ * di_read_lock_parent3, di_write_lock_parent3,
9422+ */
9423+#define AuReadLockFunc(name, lsc) \
9424+static inline void di_read_lock_##name(struct dentry *d, int flags) \
9425+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
9426+
9427+#define AuWriteLockFunc(name, lsc) \
9428+static inline void di_write_lock_##name(struct dentry *d) \
9429+{ di_write_lock(d, AuLsc_DI_##lsc); }
9430+
9431+#define AuRWLockFuncs(name, lsc) \
9432+ AuReadLockFunc(name, lsc) \
9433+ AuWriteLockFunc(name, lsc)
9434+
9435+AuRWLockFuncs(child, CHILD);
9436+AuRWLockFuncs(child2, CHILD2);
9437+AuRWLockFuncs(child3, CHILD3);
9438+AuRWLockFuncs(parent, PARENT);
9439+AuRWLockFuncs(parent2, PARENT2);
9440+AuRWLockFuncs(parent3, PARENT3);
9441+
9442+#undef AuReadLockFunc
9443+#undef AuWriteLockFunc
9444+#undef AuRWLockFuncs
9445+
9446+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
9447+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
9448+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 9449+
9450+/* ---------------------------------------------------------------------- */
9451+
9452+/* todo: memory barrier? */
9453+static inline unsigned int au_digen(struct dentry *d)
9454+{
9455+ return atomic_read(&au_di(d)->di_generation);
9456+}
9457+
9458+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
9459+{
9460+ hdentry->hd_dentry = NULL;
9461+}
9462+
5afbbe0d
AM
9463+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di,
9464+ aufs_bindex_t bindex)
9465+{
9466+ return di->di_hdentry + bindex;
9467+}
9468+
1facf9fc 9469+static inline void au_hdput(struct au_hdentry *hd)
9470+{
4a4d8108
AM
9471+ if (hd)
9472+ dput(hd->hd_dentry);
1facf9fc 9473+}
9474+
5afbbe0d 9475+static inline aufs_bindex_t au_dbtop(struct dentry *dentry)
1facf9fc 9476+{
1308ab2a 9477+ DiMustAnyLock(dentry);
5afbbe0d 9478+ return au_di(dentry)->di_btop;
1facf9fc 9479+}
9480+
5afbbe0d 9481+static inline aufs_bindex_t au_dbbot(struct dentry *dentry)
1facf9fc 9482+{
1308ab2a 9483+ DiMustAnyLock(dentry);
5afbbe0d 9484+ return au_di(dentry)->di_bbot;
1facf9fc 9485+}
9486+
9487+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
9488+{
1308ab2a 9489+ DiMustAnyLock(dentry);
1facf9fc 9490+ return au_di(dentry)->di_bwh;
9491+}
9492+
9493+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
9494+{
1308ab2a 9495+ DiMustAnyLock(dentry);
1facf9fc 9496+ return au_di(dentry)->di_bdiropq;
9497+}
9498+
9499+/* todo: hard/soft set? */
5afbbe0d 9500+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9501+{
1308ab2a 9502+ DiMustWriteLock(dentry);
5afbbe0d 9503+ au_di(dentry)->di_btop = bindex;
1facf9fc 9504+}
9505+
5afbbe0d 9506+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9507+{
1308ab2a 9508+ DiMustWriteLock(dentry);
5afbbe0d 9509+ au_di(dentry)->di_bbot = bindex;
1facf9fc 9510+}
9511+
9512+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
9513+{
1308ab2a 9514+ DiMustWriteLock(dentry);
5afbbe0d 9515+ /* dbwh can be outside of btop - bbot range */
1facf9fc 9516+ au_di(dentry)->di_bwh = bindex;
9517+}
9518+
9519+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
9520+{
1308ab2a 9521+ DiMustWriteLock(dentry);
1facf9fc 9522+ au_di(dentry)->di_bdiropq = bindex;
9523+}
9524+
9525+/* ---------------------------------------------------------------------- */
9526+
4a4d8108 9527+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 9528+static inline void au_digen_dec(struct dentry *d)
9529+{
e49829fe 9530+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 9531+}
9532+
4a4d8108 9533+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 9534+{
9535+ dentry->d_fsdata = NULL;
9536+}
9537+#else
4a4d8108
AM
9538+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
9539+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 9540+
9541+#endif /* __KERNEL__ */
9542+#endif /* __AUFS_DENTRY_H__ */
7f207e10 9543diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
fbc438ed
JR
9544--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 08:00:00.000000000 +0800
9545+++ linux/fs/aufs/dinfo.c 2019-07-11 21:21:54.379051070 +0800
062440b3 9546@@ -0,0 +1,554 @@
cd7a4cd9 9547+// SPDX-License-Identifier: GPL-2.0
1facf9fc 9548+/*
ba1aed25 9549+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 9550+ *
9551+ * This program, aufs is free software; you can redistribute it and/or modify
9552+ * it under the terms of the GNU General Public License as published by
9553+ * the Free Software Foundation; either version 2 of the License, or
9554+ * (at your option) any later version.
dece6358
AM
9555+ *
9556+ * This program is distributed in the hope that it will be useful,
9557+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9558+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9559+ * GNU General Public License for more details.
9560+ *
9561+ * You should have received a copy of the GNU General Public License
523b37e3 9562+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9563+ */
9564+
9565+/*
9566+ * dentry private data
9567+ */
9568+
9569+#include "aufs.h"
9570+
e49829fe 9571+void au_di_init_once(void *_dinfo)
4a4d8108 9572+{
e49829fe 9573+ struct au_dinfo *dinfo = _dinfo;
4a4d8108 9574+
e49829fe 9575+ au_rw_init(&dinfo->di_rwsem);
4a4d8108
AM
9576+}
9577+
027c5e7a 9578+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 9579+{
9580+ struct au_dinfo *dinfo;
027c5e7a 9581+ int nbr, i;
1facf9fc 9582+
9583+ dinfo = au_cache_alloc_dinfo();
9584+ if (unlikely(!dinfo))
9585+ goto out;
9586+
5afbbe0d 9587+ nbr = au_sbbot(sb) + 1;
1facf9fc 9588+ if (nbr <= 0)
9589+ nbr = 1;
9590+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
9591+ if (dinfo->di_hdentry) {
9592+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
5afbbe0d
AM
9593+ dinfo->di_btop = -1;
9594+ dinfo->di_bbot = -1;
027c5e7a
AM
9595+ dinfo->di_bwh = -1;
9596+ dinfo->di_bdiropq = -1;
38d290e6 9597+ dinfo->di_tmpfile = 0;
027c5e7a
AM
9598+ for (i = 0; i < nbr; i++)
9599+ dinfo->di_hdentry[i].hd_id = -1;
9600+ goto out;
9601+ }
1facf9fc 9602+
1c60b727 9603+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9604+ dinfo = NULL;
9605+
4f0767ce 9606+out:
027c5e7a 9607+ return dinfo;
1facf9fc 9608+}
9609+
027c5e7a 9610+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 9611+{
4a4d8108 9612+ struct au_hdentry *p;
5afbbe0d 9613+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
9614+
9615+ /* dentry may not be revalidated */
5afbbe0d 9616+ bindex = dinfo->di_btop;
4a4d8108 9617+ if (bindex >= 0) {
5afbbe0d
AM
9618+ bbot = dinfo->di_bbot;
9619+ p = au_hdentry(dinfo, bindex);
9620+ while (bindex++ <= bbot)
4a4d8108
AM
9621+ au_hdput(p++);
9622+ }
9f237c51 9623+ au_kfree_try_rcu(dinfo->di_hdentry);
1c60b727 9624+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9625+}
9626+
9627+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
9628+{
9629+ struct au_hdentry *p;
9630+ aufs_bindex_t bi;
9631+
9632+ AuRwMustWriteLock(&a->di_rwsem);
9633+ AuRwMustWriteLock(&b->di_rwsem);
9634+
9635+#define DiSwap(v, name) \
9636+ do { \
9637+ v = a->di_##name; \
9638+ a->di_##name = b->di_##name; \
9639+ b->di_##name = v; \
9640+ } while (0)
9641+
9642+ DiSwap(p, hdentry);
5afbbe0d
AM
9643+ DiSwap(bi, btop);
9644+ DiSwap(bi, bbot);
027c5e7a
AM
9645+ DiSwap(bi, bwh);
9646+ DiSwap(bi, bdiropq);
9647+ /* smp_mb(); */
9648+
9649+#undef DiSwap
9650+}
9651+
9652+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
9653+{
9654+ AuRwMustWriteLock(&dst->di_rwsem);
9655+ AuRwMustWriteLock(&src->di_rwsem);
9656+
5afbbe0d
AM
9657+ dst->di_btop = src->di_btop;
9658+ dst->di_bbot = src->di_bbot;
027c5e7a
AM
9659+ dst->di_bwh = src->di_bwh;
9660+ dst->di_bdiropq = src->di_bdiropq;
9661+ /* smp_mb(); */
9662+}
9663+
9664+int au_di_init(struct dentry *dentry)
9665+{
9666+ int err;
9667+ struct super_block *sb;
9668+ struct au_dinfo *dinfo;
9669+
9670+ err = 0;
9671+ sb = dentry->d_sb;
9672+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
9673+ if (dinfo) {
9674+ atomic_set(&dinfo->di_generation, au_sigen(sb));
9675+ /* smp_mb(); */ /* atomic_set */
9676+ dentry->d_fsdata = dinfo;
9677+ } else
9678+ err = -ENOMEM;
9679+
9680+ return err;
9681+}
9682+
9683+void au_di_fin(struct dentry *dentry)
9684+{
9685+ struct au_dinfo *dinfo;
9686+
9687+ dinfo = au_di(dentry);
9688+ AuRwDestroy(&dinfo->di_rwsem);
9689+ au_di_free(dinfo);
4a4d8108
AM
9690+}
9691+
e2f27e51 9692+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink)
1facf9fc 9693+{
9694+ int err, sz;
9695+ struct au_hdentry *hdp;
9696+
1308ab2a 9697+ AuRwMustWriteLock(&dinfo->di_rwsem);
9698+
1facf9fc 9699+ err = -ENOMEM;
5afbbe0d 9700+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1);
1facf9fc 9701+ if (!sz)
9702+ sz = sizeof(*hdp);
e2f27e51
AM
9703+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS,
9704+ may_shrink);
1facf9fc 9705+ if (hdp) {
9706+ dinfo->di_hdentry = hdp;
9707+ err = 0;
9708+ }
9709+
9710+ return err;
9711+}
9712+
9713+/* ---------------------------------------------------------------------- */
9714+
9715+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
9716+{
9717+ switch (lsc) {
9718+ case AuLsc_DI_CHILD:
9719+ ii_write_lock_child(inode);
9720+ break;
9721+ case AuLsc_DI_CHILD2:
9722+ ii_write_lock_child2(inode);
9723+ break;
9724+ case AuLsc_DI_CHILD3:
9725+ ii_write_lock_child3(inode);
9726+ break;
9727+ case AuLsc_DI_PARENT:
9728+ ii_write_lock_parent(inode);
9729+ break;
9730+ case AuLsc_DI_PARENT2:
9731+ ii_write_lock_parent2(inode);
9732+ break;
9733+ case AuLsc_DI_PARENT3:
9734+ ii_write_lock_parent3(inode);
9735+ break;
9736+ default:
9737+ BUG();
9738+ }
9739+}
9740+
9741+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
9742+{
9743+ switch (lsc) {
9744+ case AuLsc_DI_CHILD:
9745+ ii_read_lock_child(inode);
9746+ break;
9747+ case AuLsc_DI_CHILD2:
9748+ ii_read_lock_child2(inode);
9749+ break;
9750+ case AuLsc_DI_CHILD3:
9751+ ii_read_lock_child3(inode);
9752+ break;
9753+ case AuLsc_DI_PARENT:
9754+ ii_read_lock_parent(inode);
9755+ break;
9756+ case AuLsc_DI_PARENT2:
9757+ ii_read_lock_parent2(inode);
9758+ break;
9759+ case AuLsc_DI_PARENT3:
9760+ ii_read_lock_parent3(inode);
9761+ break;
9762+ default:
9763+ BUG();
9764+ }
9765+}
9766+
9767+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
9768+{
5527c038
JR
9769+ struct inode *inode;
9770+
dece6358 9771+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9772+ if (d_really_is_positive(d)) {
9773+ inode = d_inode(d);
1facf9fc 9774+ if (au_ftest_lock(flags, IW))
5527c038 9775+ do_ii_write_lock(inode, lsc);
1facf9fc 9776+ else if (au_ftest_lock(flags, IR))
5527c038 9777+ do_ii_read_lock(inode, lsc);
1facf9fc 9778+ }
9779+}
9780+
9781+void di_read_unlock(struct dentry *d, int flags)
9782+{
5527c038
JR
9783+ struct inode *inode;
9784+
9785+ if (d_really_is_positive(d)) {
9786+ inode = d_inode(d);
027c5e7a
AM
9787+ if (au_ftest_lock(flags, IW)) {
9788+ au_dbg_verify_dinode(d);
5527c038 9789+ ii_write_unlock(inode);
027c5e7a
AM
9790+ } else if (au_ftest_lock(flags, IR)) {
9791+ au_dbg_verify_dinode(d);
5527c038 9792+ ii_read_unlock(inode);
027c5e7a 9793+ }
1facf9fc 9794+ }
dece6358 9795+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 9796+}
9797+
9798+void di_downgrade_lock(struct dentry *d, int flags)
9799+{
5527c038
JR
9800+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR))
9801+ ii_downgrade_lock(d_inode(d));
dece6358 9802+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 9803+}
9804+
9805+void di_write_lock(struct dentry *d, unsigned int lsc)
9806+{
dece6358 9807+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9808+ if (d_really_is_positive(d))
9809+ do_ii_write_lock(d_inode(d), lsc);
1facf9fc 9810+}
9811+
9812+void di_write_unlock(struct dentry *d)
9813+{
027c5e7a 9814+ au_dbg_verify_dinode(d);
5527c038
JR
9815+ if (d_really_is_positive(d))
9816+ ii_write_unlock(d_inode(d));
dece6358 9817+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 9818+}
9819+
9820+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
9821+{
9822+ AuDebugOn(d1 == d2
5527c038 9823+ || d_inode(d1) == d_inode(d2)
1facf9fc 9824+ || d1->d_sb != d2->d_sb);
9825+
521ced18
JR
9826+ if ((isdir && au_test_subdir(d1, d2))
9827+ || d1 < d2) {
1facf9fc 9828+ di_write_lock_child(d1);
9829+ di_write_lock_child2(d2);
9830+ } else {
1facf9fc 9831+ di_write_lock_child(d2);
9832+ di_write_lock_child2(d1);
9833+ }
9834+}
9835+
9836+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
9837+{
9838+ AuDebugOn(d1 == d2
5527c038 9839+ || d_inode(d1) == d_inode(d2)
1facf9fc 9840+ || d1->d_sb != d2->d_sb);
9841+
521ced18
JR
9842+ if ((isdir && au_test_subdir(d1, d2))
9843+ || d1 < d2) {
1facf9fc 9844+ di_write_lock_parent(d1);
9845+ di_write_lock_parent2(d2);
9846+ } else {
1facf9fc 9847+ di_write_lock_parent(d2);
9848+ di_write_lock_parent2(d1);
9849+ }
9850+}
9851+
9852+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
9853+{
9854+ di_write_unlock(d1);
5527c038 9855+ if (d_inode(d1) == d_inode(d2))
dece6358 9856+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 9857+ else
9858+ di_write_unlock(d2);
9859+}
9860+
9861+/* ---------------------------------------------------------------------- */
9862+
9863+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
9864+{
9865+ struct dentry *d;
9866+
1308ab2a 9867+ DiMustAnyLock(dentry);
9868+
5afbbe0d 9869+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
1facf9fc 9870+ return NULL;
9871+ AuDebugOn(bindex < 0);
5afbbe0d 9872+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry;
c1595e42 9873+ AuDebugOn(d && au_dcount(d) <= 0);
1facf9fc 9874+ return d;
9875+}
9876+
2cbb1c4b
JR
9877+/*
9878+ * extended version of au_h_dptr().
38d290e6
JR
9879+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or
9880+ * error.
2cbb1c4b
JR
9881+ */
9882+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
9883+{
9884+ struct dentry *h_dentry;
9885+ struct inode *inode, *h_inode;
9886+
5527c038 9887+ AuDebugOn(d_really_is_negative(dentry));
2cbb1c4b
JR
9888+
9889+ h_dentry = NULL;
5afbbe0d
AM
9890+ if (au_dbtop(dentry) <= bindex
9891+ && bindex <= au_dbbot(dentry))
2cbb1c4b 9892+ h_dentry = au_h_dptr(dentry, bindex);
38d290e6 9893+ if (h_dentry && !au_d_linkable(h_dentry)) {
2cbb1c4b
JR
9894+ dget(h_dentry);
9895+ goto out; /* success */
9896+ }
9897+
5527c038 9898+ inode = d_inode(dentry);
5afbbe0d
AM
9899+ AuDebugOn(bindex < au_ibtop(inode));
9900+ AuDebugOn(au_ibbot(inode) < bindex);
2cbb1c4b
JR
9901+ h_inode = au_h_iptr(inode, bindex);
9902+ h_dentry = d_find_alias(h_inode);
9903+ if (h_dentry) {
9904+ if (!IS_ERR(h_dentry)) {
38d290e6 9905+ if (!au_d_linkable(h_dentry))
2cbb1c4b
JR
9906+ goto out; /* success */
9907+ dput(h_dentry);
9908+ } else
9909+ goto out;
9910+ }
9911+
9912+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
9913+ h_dentry = au_plink_lkup(inode, bindex);
9914+ AuDebugOn(!h_dentry);
9915+ if (!IS_ERR(h_dentry)) {
9916+ if (!au_d_hashed_positive(h_dentry))
9917+ goto out; /* success */
9918+ dput(h_dentry);
9919+ h_dentry = NULL;
9920+ }
9921+ }
9922+
9923+out:
9924+ AuDbgDentry(h_dentry);
9925+ return h_dentry;
9926+}
9927+
1facf9fc 9928+aufs_bindex_t au_dbtail(struct dentry *dentry)
9929+{
5afbbe0d 9930+ aufs_bindex_t bbot, bwh;
1facf9fc 9931+
5afbbe0d
AM
9932+ bbot = au_dbbot(dentry);
9933+ if (0 <= bbot) {
1facf9fc 9934+ bwh = au_dbwh(dentry);
9935+ if (!bwh)
9936+ return bwh;
5afbbe0d 9937+ if (0 < bwh && bwh < bbot)
1facf9fc 9938+ return bwh - 1;
9939+ }
5afbbe0d 9940+ return bbot;
1facf9fc 9941+}
9942+
9943+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
9944+{
5afbbe0d 9945+ aufs_bindex_t bbot, bopq;
1facf9fc 9946+
5afbbe0d
AM
9947+ bbot = au_dbtail(dentry);
9948+ if (0 <= bbot) {
1facf9fc 9949+ bopq = au_dbdiropq(dentry);
5afbbe0d
AM
9950+ if (0 <= bopq && bopq < bbot)
9951+ bbot = bopq;
1facf9fc 9952+ }
5afbbe0d 9953+ return bbot;
1facf9fc 9954+}
9955+
9956+/* ---------------------------------------------------------------------- */
9957+
9958+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9959+ struct dentry *h_dentry)
9960+{
5afbbe0d
AM
9961+ struct au_dinfo *dinfo;
9962+ struct au_hdentry *hd;
027c5e7a 9963+ struct au_branch *br;
1facf9fc 9964+
1308ab2a 9965+ DiMustWriteLock(dentry);
9966+
5afbbe0d
AM
9967+ dinfo = au_di(dentry);
9968+ hd = au_hdentry(dinfo, bindex);
4a4d8108 9969+ au_hdput(hd);
1facf9fc 9970+ hd->hd_dentry = h_dentry;
027c5e7a
AM
9971+ if (h_dentry) {
9972+ br = au_sbr(dentry->d_sb, bindex);
9973+ hd->hd_id = br->br_id;
9974+ }
9975+}
9976+
9977+int au_dbrange_test(struct dentry *dentry)
9978+{
9979+ int err;
5afbbe0d 9980+ aufs_bindex_t btop, bbot;
027c5e7a
AM
9981+
9982+ err = 0;
5afbbe0d
AM
9983+ btop = au_dbtop(dentry);
9984+ bbot = au_dbbot(dentry);
9985+ if (btop >= 0)
9986+ AuDebugOn(bbot < 0 && btop > bbot);
027c5e7a
AM
9987+ else {
9988+ err = -EIO;
5afbbe0d 9989+ AuDebugOn(bbot >= 0);
027c5e7a
AM
9990+ }
9991+
9992+ return err;
9993+}
9994+
9995+int au_digen_test(struct dentry *dentry, unsigned int sigen)
9996+{
9997+ int err;
9998+
9999+ err = 0;
10000+ if (unlikely(au_digen(dentry) != sigen
5527c038 10001+ || au_iigen_test(d_inode(dentry), sigen)))
027c5e7a
AM
10002+ err = -EIO;
10003+
10004+ return err;
1facf9fc 10005+}
10006+
10007+void au_update_digen(struct dentry *dentry)
10008+{
10009+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
10010+ /* smp_mb(); */ /* atomic_set */
10011+}
10012+
10013+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
10014+{
10015+ struct au_dinfo *dinfo;
10016+ struct dentry *h_d;
4a4d8108 10017+ struct au_hdentry *hdp;
5afbbe0d 10018+ aufs_bindex_t bindex, bbot;
1facf9fc 10019+
1308ab2a 10020+ DiMustWriteLock(dentry);
10021+
1facf9fc 10022+ dinfo = au_di(dentry);
5afbbe0d 10023+ if (!dinfo || dinfo->di_btop < 0)
1facf9fc 10024+ return;
10025+
10026+ if (do_put_zero) {
5afbbe0d
AM
10027+ bbot = dinfo->di_bbot;
10028+ bindex = dinfo->di_btop;
10029+ hdp = au_hdentry(dinfo, bindex);
10030+ for (; bindex <= bbot; bindex++, hdp++) {
10031+ h_d = hdp->hd_dentry;
5527c038 10032+ if (h_d && d_is_negative(h_d))
1facf9fc 10033+ au_set_h_dptr(dentry, bindex, NULL);
10034+ }
10035+ }
10036+
5afbbe0d
AM
10037+ dinfo->di_btop = 0;
10038+ hdp = au_hdentry(dinfo, dinfo->di_btop);
10039+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++)
10040+ if (hdp->hd_dentry)
1facf9fc 10041+ break;
5afbbe0d
AM
10042+ if (dinfo->di_btop > dinfo->di_bbot) {
10043+ dinfo->di_btop = -1;
10044+ dinfo->di_bbot = -1;
1facf9fc 10045+ return;
10046+ }
10047+
5afbbe0d
AM
10048+ hdp = au_hdentry(dinfo, dinfo->di_bbot);
10049+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--)
10050+ if (hdp->hd_dentry)
1facf9fc 10051+ break;
5afbbe0d 10052+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0);
1facf9fc 10053+}
10054+
5afbbe0d 10055+void au_update_dbtop(struct dentry *dentry)
1facf9fc 10056+{
5afbbe0d 10057+ aufs_bindex_t bindex, bbot;
1facf9fc 10058+ struct dentry *h_dentry;
10059+
5afbbe0d
AM
10060+ bbot = au_dbbot(dentry);
10061+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
1facf9fc 10062+ h_dentry = au_h_dptr(dentry, bindex);
10063+ if (!h_dentry)
10064+ continue;
5527c038 10065+ if (d_is_positive(h_dentry)) {
5afbbe0d 10066+ au_set_dbtop(dentry, bindex);
1facf9fc 10067+ return;
10068+ }
10069+ au_set_h_dptr(dentry, bindex, NULL);
10070+ }
10071+}
10072+
5afbbe0d 10073+void au_update_dbbot(struct dentry *dentry)
1facf9fc 10074+{
5afbbe0d 10075+ aufs_bindex_t bindex, btop;
1facf9fc 10076+ struct dentry *h_dentry;
10077+
5afbbe0d
AM
10078+ btop = au_dbtop(dentry);
10079+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) {
1facf9fc 10080+ h_dentry = au_h_dptr(dentry, bindex);
10081+ if (!h_dentry)
10082+ continue;
5527c038 10083+ if (d_is_positive(h_dentry)) {
5afbbe0d 10084+ au_set_dbbot(dentry, bindex);
1facf9fc 10085+ return;
10086+ }
10087+ au_set_h_dptr(dentry, bindex, NULL);
10088+ }
10089+}
10090+
10091+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
10092+{
5afbbe0d 10093+ aufs_bindex_t bindex, bbot;
1facf9fc 10094+
5afbbe0d
AM
10095+ bbot = au_dbbot(dentry);
10096+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++)
1facf9fc 10097+ if (au_h_dptr(dentry, bindex) == h_dentry)
10098+ return bindex;
10099+ return -1;
10100+}
7f207e10 10101diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
fbc438ed
JR
10102--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 08:00:00.000000000 +0800
10103+++ linux/fs/aufs/dir.c 2019-07-11 21:21:54.379051070 +0800
eca801bf 10104@@ -0,0 +1,763 @@
cd7a4cd9 10105+// SPDX-License-Identifier: GPL-2.0
1facf9fc 10106+/*
ba1aed25 10107+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 10108+ *
10109+ * This program, aufs is free software; you can redistribute it and/or modify
10110+ * it under the terms of the GNU General Public License as published by
10111+ * the Free Software Foundation; either version 2 of the License, or
10112+ * (at your option) any later version.
dece6358
AM
10113+ *
10114+ * This program is distributed in the hope that it will be useful,
10115+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10116+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10117+ * GNU General Public License for more details.
10118+ *
10119+ * You should have received a copy of the GNU General Public License
523b37e3 10120+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10121+ */
10122+
10123+/*
10124+ * directory operations
10125+ */
10126+
10127+#include <linux/fs_stack.h>
eca801bf 10128+#include <linux/iversion.h>
1facf9fc 10129+#include "aufs.h"
10130+
10131+void au_add_nlink(struct inode *dir, struct inode *h_dir)
10132+{
9dbd164d
AM
10133+ unsigned int nlink;
10134+
1facf9fc 10135+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
10136+
9dbd164d
AM
10137+ nlink = dir->i_nlink;
10138+ nlink += h_dir->i_nlink - 2;
1facf9fc 10139+ if (h_dir->i_nlink < 2)
9dbd164d 10140+ nlink += 2;
f6b6e03d 10141+ smp_mb(); /* for i_nlink */
7eafdf33 10142+ /* 0 can happen in revaliding */
92d182d2 10143+ set_nlink(dir, nlink);
1facf9fc 10144+}
10145+
10146+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
10147+{
9dbd164d
AM
10148+ unsigned int nlink;
10149+
1facf9fc 10150+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
10151+
9dbd164d
AM
10152+ nlink = dir->i_nlink;
10153+ nlink -= h_dir->i_nlink - 2;
1facf9fc 10154+ if (h_dir->i_nlink < 2)
9dbd164d 10155+ nlink -= 2;
f6b6e03d 10156+ smp_mb(); /* for i_nlink */
92d182d2 10157+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 10158+ set_nlink(dir, nlink);
1facf9fc 10159+}
10160+
1308ab2a 10161+loff_t au_dir_size(struct file *file, struct dentry *dentry)
10162+{
10163+ loff_t sz;
5afbbe0d 10164+ aufs_bindex_t bindex, bbot;
1308ab2a 10165+ struct file *h_file;
10166+ struct dentry *h_dentry;
10167+
10168+ sz = 0;
10169+ if (file) {
2000de60 10170+ AuDebugOn(!d_is_dir(file->f_path.dentry));
1308ab2a 10171+
5afbbe0d
AM
10172+ bbot = au_fbbot_dir(file);
10173+ for (bindex = au_fbtop(file);
10174+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10175+ bindex++) {
4a4d8108 10176+ h_file = au_hf_dir(file, bindex);
c06a8ce3
AM
10177+ if (h_file && file_inode(h_file))
10178+ sz += vfsub_f_size_read(h_file);
1308ab2a 10179+ }
10180+ } else {
10181+ AuDebugOn(!dentry);
2000de60 10182+ AuDebugOn(!d_is_dir(dentry));
1308ab2a 10183+
5afbbe0d
AM
10184+ bbot = au_dbtaildir(dentry);
10185+ for (bindex = au_dbtop(dentry);
10186+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10187+ bindex++) {
10188+ h_dentry = au_h_dptr(dentry, bindex);
5527c038
JR
10189+ if (h_dentry && d_is_positive(h_dentry))
10190+ sz += i_size_read(d_inode(h_dentry));
1308ab2a 10191+ }
10192+ }
10193+ if (sz < KMALLOC_MAX_SIZE)
10194+ sz = roundup_pow_of_two(sz);
10195+ if (sz > KMALLOC_MAX_SIZE)
10196+ sz = KMALLOC_MAX_SIZE;
10197+ else if (sz < NAME_MAX) {
10198+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
10199+ sz = AUFS_RDBLK_DEF;
10200+ }
10201+ return sz;
10202+}
10203+
b912730e
AM
10204+struct au_dir_ts_arg {
10205+ struct dentry *dentry;
10206+ aufs_bindex_t brid;
10207+};
10208+
10209+static void au_do_dir_ts(void *arg)
10210+{
10211+ struct au_dir_ts_arg *a = arg;
10212+ struct au_dtime dt;
10213+ struct path h_path;
10214+ struct inode *dir, *h_dir;
10215+ struct super_block *sb;
10216+ struct au_branch *br;
10217+ struct au_hinode *hdir;
10218+ int err;
5afbbe0d 10219+ aufs_bindex_t btop, bindex;
b912730e
AM
10220+
10221+ sb = a->dentry->d_sb;
5527c038 10222+ if (d_really_is_negative(a->dentry))
b912730e 10223+ goto out;
5527c038 10224+ /* no dir->i_mutex lock */
b95c5147
AM
10225+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */
10226+
5527c038 10227+ dir = d_inode(a->dentry);
5afbbe0d 10228+ btop = au_ibtop(dir);
b912730e 10229+ bindex = au_br_index(sb, a->brid);
5afbbe0d 10230+ if (bindex < btop)
b912730e
AM
10231+ goto out_unlock;
10232+
10233+ br = au_sbr(sb, bindex);
10234+ h_path.dentry = au_h_dptr(a->dentry, bindex);
10235+ if (!h_path.dentry)
10236+ goto out_unlock;
10237+ h_path.mnt = au_br_mnt(br);
10238+ au_dtime_store(&dt, a->dentry, &h_path);
10239+
5afbbe0d 10240+ br = au_sbr(sb, btop);
b912730e
AM
10241+ if (!au_br_writable(br->br_perm))
10242+ goto out_unlock;
5afbbe0d 10243+ h_path.dentry = au_h_dptr(a->dentry, btop);
b912730e
AM
10244+ h_path.mnt = au_br_mnt(br);
10245+ err = vfsub_mnt_want_write(h_path.mnt);
10246+ if (err)
10247+ goto out_unlock;
5afbbe0d
AM
10248+ hdir = au_hi(dir, btop);
10249+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
10250+ h_dir = au_h_iptr(dir, btop);
b912730e 10251+ if (h_dir->i_nlink
cd7a4cd9 10252+ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) {
b912730e
AM
10253+ dt.dt_h_path = h_path;
10254+ au_dtime_revert(&dt);
10255+ }
5afbbe0d 10256+ au_hn_inode_unlock(hdir);
b912730e
AM
10257+ vfsub_mnt_drop_write(h_path.mnt);
10258+ au_cpup_attr_timesizes(dir);
10259+
10260+out_unlock:
10261+ aufs_read_unlock(a->dentry, AuLock_DW);
10262+out:
10263+ dput(a->dentry);
10264+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 10265+ au_kfree_try_rcu(arg);
b912730e
AM
10266+}
10267+
10268+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
10269+{
10270+ int perm, wkq_err;
5afbbe0d 10271+ aufs_bindex_t btop;
b912730e
AM
10272+ struct au_dir_ts_arg *arg;
10273+ struct dentry *dentry;
10274+ struct super_block *sb;
10275+
10276+ IMustLock(dir);
10277+
10278+ dentry = d_find_any_alias(dir);
10279+ AuDebugOn(!dentry);
10280+ sb = dentry->d_sb;
5afbbe0d
AM
10281+ btop = au_ibtop(dir);
10282+ if (btop == bindex) {
b912730e
AM
10283+ au_cpup_attr_timesizes(dir);
10284+ goto out;
10285+ }
10286+
5afbbe0d 10287+ perm = au_sbr_perm(sb, btop);
b912730e
AM
10288+ if (!au_br_writable(perm))
10289+ goto out;
10290+
10291+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
10292+ if (!arg)
10293+ goto out;
10294+
10295+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */
10296+ arg->brid = au_sbr_id(sb, bindex);
10297+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0);
10298+ if (unlikely(wkq_err)) {
10299+ pr_err("wkq %d\n", wkq_err);
10300+ dput(dentry);
9f237c51 10301+ au_kfree_try_rcu(arg);
b912730e
AM
10302+ }
10303+
10304+out:
10305+ dput(dentry);
10306+}
10307+
1facf9fc 10308+/* ---------------------------------------------------------------------- */
10309+
10310+static int reopen_dir(struct file *file)
10311+{
10312+ int err;
10313+ unsigned int flags;
5afbbe0d 10314+ aufs_bindex_t bindex, btail, btop;
1facf9fc 10315+ struct dentry *dentry, *h_dentry;
10316+ struct file *h_file;
10317+
10318+ /* open all lower dirs */
2000de60 10319+ dentry = file->f_path.dentry;
5afbbe0d
AM
10320+ btop = au_dbtop(dentry);
10321+ for (bindex = au_fbtop(file); bindex < btop; bindex++)
1facf9fc 10322+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10323+ au_set_fbtop(file, btop);
1facf9fc 10324+
10325+ btail = au_dbtaildir(dentry);
5afbbe0d 10326+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--)
1facf9fc 10327+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10328+ au_set_fbbot_dir(file, btail);
1facf9fc 10329+
4a4d8108 10330+ flags = vfsub_file_flags(file);
5afbbe0d 10331+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 10332+ h_dentry = au_h_dptr(dentry, bindex);
10333+ if (!h_dentry)
10334+ continue;
4a4d8108 10335+ h_file = au_hf_dir(file, bindex);
1facf9fc 10336+ if (h_file)
10337+ continue;
10338+
392086de 10339+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10340+ err = PTR_ERR(h_file);
10341+ if (IS_ERR(h_file))
10342+ goto out; /* close all? */
10343+ au_set_h_fptr(file, bindex, h_file);
10344+ }
10345+ au_update_figen(file);
10346+ /* todo: necessary? */
10347+ /* file->f_ra = h_file->f_ra; */
10348+ err = 0;
10349+
4f0767ce 10350+out:
1facf9fc 10351+ return err;
10352+}
10353+
b912730e 10354+static int do_open_dir(struct file *file, int flags, struct file *h_file)
1facf9fc 10355+{
10356+ int err;
10357+ aufs_bindex_t bindex, btail;
10358+ struct dentry *dentry, *h_dentry;
8cdd5066 10359+ struct vfsmount *mnt;
1facf9fc 10360+
1308ab2a 10361+ FiMustWriteLock(file);
b912730e 10362+ AuDebugOn(h_file);
1308ab2a 10363+
523b37e3 10364+ err = 0;
8cdd5066 10365+ mnt = file->f_path.mnt;
2000de60 10366+ dentry = file->f_path.dentry;
be118d29 10367+ file->f_version = inode_query_iversion(d_inode(dentry));
5afbbe0d
AM
10368+ bindex = au_dbtop(dentry);
10369+ au_set_fbtop(file, bindex);
1facf9fc 10370+ btail = au_dbtaildir(dentry);
5afbbe0d 10371+ au_set_fbbot_dir(file, btail);
1facf9fc 10372+ for (; !err && bindex <= btail; bindex++) {
10373+ h_dentry = au_h_dptr(dentry, bindex);
10374+ if (!h_dentry)
10375+ continue;
10376+
8cdd5066
JR
10377+ err = vfsub_test_mntns(mnt, h_dentry->d_sb);
10378+ if (unlikely(err))
10379+ break;
392086de 10380+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10381+ if (IS_ERR(h_file)) {
10382+ err = PTR_ERR(h_file);
10383+ break;
10384+ }
10385+ au_set_h_fptr(file, bindex, h_file);
10386+ }
10387+ au_update_figen(file);
10388+ /* todo: necessary? */
10389+ /* file->f_ra = h_file->f_ra; */
10390+ if (!err)
10391+ return 0; /* success */
10392+
10393+ /* close all */
5afbbe0d 10394+ for (bindex = au_fbtop(file); bindex <= btail; bindex++)
1facf9fc 10395+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d
AM
10396+ au_set_fbtop(file, -1);
10397+ au_set_fbbot_dir(file, -1);
4a4d8108 10398+
1facf9fc 10399+ return err;
10400+}
10401+
10402+static int aufs_open_dir(struct inode *inode __maybe_unused,
10403+ struct file *file)
10404+{
4a4d8108
AM
10405+ int err;
10406+ struct super_block *sb;
10407+ struct au_fidir *fidir;
10408+
10409+ err = -ENOMEM;
2000de60 10410+ sb = file->f_path.dentry->d_sb;
4a4d8108 10411+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 10412+ fidir = au_fidir_alloc(sb);
4a4d8108 10413+ if (fidir) {
b912730e
AM
10414+ struct au_do_open_args args = {
10415+ .open = do_open_dir,
10416+ .fidir = fidir
10417+ };
10418+ err = au_do_open(file, &args);
4a4d8108 10419+ if (unlikely(err))
9f237c51 10420+ au_kfree_rcu(fidir);
4a4d8108
AM
10421+ }
10422+ si_read_unlock(sb);
10423+ return err;
1facf9fc 10424+}
10425+
10426+static int aufs_release_dir(struct inode *inode __maybe_unused,
10427+ struct file *file)
10428+{
10429+ struct au_vdir *vdir_cache;
4a4d8108
AM
10430+ struct au_finfo *finfo;
10431+ struct au_fidir *fidir;
f0c0a007 10432+ struct au_hfile *hf;
5afbbe0d 10433+ aufs_bindex_t bindex, bbot;
1facf9fc 10434+
4a4d8108
AM
10435+ finfo = au_fi(file);
10436+ fidir = finfo->fi_hdir;
10437+ if (fidir) {
8b6a4947
AM
10438+ au_hbl_del(&finfo->fi_hlist,
10439+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108
AM
10440+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
10441+ if (vdir_cache)
1c60b727 10442+ au_vdir_free(vdir_cache);
4a4d8108
AM
10443+
10444+ bindex = finfo->fi_btop;
10445+ if (bindex >= 0) {
f0c0a007 10446+ hf = fidir->fd_hfile + bindex;
4a4d8108
AM
10447+ /*
10448+ * calls fput() instead of filp_close(),
10449+ * since no dnotify or lock for the lower file.
10450+ */
5afbbe0d 10451+ bbot = fidir->fd_bbot;
f0c0a007
AM
10452+ for (; bindex <= bbot; bindex++, hf++)
10453+ if (hf->hf_file)
1c60b727 10454+ au_hfput(hf, /*execed*/0);
4a4d8108 10455+ }
9f237c51 10456+ au_kfree_rcu(fidir);
4a4d8108 10457+ finfo->fi_hdir = NULL;
1facf9fc 10458+ }
1c60b727 10459+ au_finfo_fin(file);
1facf9fc 10460+ return 0;
10461+}
10462+
10463+/* ---------------------------------------------------------------------- */
10464+
4a4d8108
AM
10465+static int au_do_flush_dir(struct file *file, fl_owner_t id)
10466+{
10467+ int err;
5afbbe0d 10468+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
10469+ struct file *h_file;
10470+
10471+ err = 0;
5afbbe0d
AM
10472+ bbot = au_fbbot_dir(file);
10473+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
10474+ h_file = au_hf_dir(file, bindex);
10475+ if (h_file)
10476+ err = vfsub_flush(h_file, id);
10477+ }
10478+ return err;
10479+}
10480+
10481+static int aufs_flush_dir(struct file *file, fl_owner_t id)
10482+{
10483+ return au_do_flush(file, id, au_do_flush_dir);
10484+}
10485+
10486+/* ---------------------------------------------------------------------- */
10487+
1facf9fc 10488+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
10489+{
10490+ int err;
5afbbe0d 10491+ aufs_bindex_t bbot, bindex;
1facf9fc 10492+ struct inode *inode;
10493+ struct super_block *sb;
10494+
10495+ err = 0;
10496+ sb = dentry->d_sb;
5527c038 10497+ inode = d_inode(dentry);
1facf9fc 10498+ IMustLock(inode);
5afbbe0d
AM
10499+ bbot = au_dbbot(dentry);
10500+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) {
1facf9fc 10501+ struct path h_path;
1facf9fc 10502+
10503+ if (au_test_ro(sb, bindex, inode))
10504+ continue;
10505+ h_path.dentry = au_h_dptr(dentry, bindex);
10506+ if (!h_path.dentry)
10507+ continue;
1facf9fc 10508+
1facf9fc 10509+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 10510+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 10511+ }
10512+
10513+ return err;
10514+}
10515+
10516+static int au_do_fsync_dir(struct file *file, int datasync)
10517+{
10518+ int err;
5afbbe0d 10519+ aufs_bindex_t bbot, bindex;
1facf9fc 10520+ struct file *h_file;
10521+ struct super_block *sb;
10522+ struct inode *inode;
1facf9fc 10523+
521ced18 10524+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10525+ if (unlikely(err))
10526+ goto out;
10527+
c06a8ce3 10528+ inode = file_inode(file);
b912730e 10529+ sb = inode->i_sb;
5afbbe0d
AM
10530+ bbot = au_fbbot_dir(file);
10531+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108 10532+ h_file = au_hf_dir(file, bindex);
1facf9fc 10533+ if (!h_file || au_test_ro(sb, bindex, inode))
10534+ continue;
10535+
53392da6 10536+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 10537+ }
10538+
4f0767ce 10539+out:
1facf9fc 10540+ return err;
10541+}
10542+
10543+/*
10544+ * @file may be NULL
10545+ */
1e00d052
AM
10546+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
10547+ int datasync)
1facf9fc 10548+{
10549+ int err;
b752ccd1 10550+ struct dentry *dentry;
5527c038 10551+ struct inode *inode;
1facf9fc 10552+ struct super_block *sb;
1facf9fc 10553+
10554+ err = 0;
2000de60 10555+ dentry = file->f_path.dentry;
5527c038 10556+ inode = d_inode(dentry);
febd17d6 10557+ inode_lock(inode);
1facf9fc 10558+ sb = dentry->d_sb;
10559+ si_noflush_read_lock(sb);
10560+ if (file)
10561+ err = au_do_fsync_dir(file, datasync);
10562+ else {
10563+ di_write_lock_child(dentry);
10564+ err = au_do_fsync_dir_no_file(dentry, datasync);
10565+ }
5527c038 10566+ au_cpup_attr_timesizes(inode);
1facf9fc 10567+ di_write_unlock(dentry);
10568+ if (file)
10569+ fi_write_unlock(file);
10570+
10571+ si_read_unlock(sb);
febd17d6 10572+ inode_unlock(inode);
1facf9fc 10573+ return err;
10574+}
10575+
10576+/* ---------------------------------------------------------------------- */
10577+
5afbbe0d 10578+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx)
1facf9fc 10579+{
10580+ int err;
10581+ struct dentry *dentry;
9dbd164d 10582+ struct inode *inode, *h_inode;
1facf9fc 10583+ struct super_block *sb;
10584+
062440b3 10585+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 10586+
2000de60 10587+ dentry = file->f_path.dentry;
5527c038 10588+ inode = d_inode(dentry);
1facf9fc 10589+ IMustLock(inode);
10590+
10591+ sb = dentry->d_sb;
10592+ si_read_lock(sb, AuLock_FLUSH);
521ced18 10593+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10594+ if (unlikely(err))
10595+ goto out;
027c5e7a
AM
10596+ err = au_alive_dir(dentry);
10597+ if (!err)
10598+ err = au_vdir_init(file);
1facf9fc 10599+ di_downgrade_lock(dentry, AuLock_IR);
10600+ if (unlikely(err))
10601+ goto out_unlock;
10602+
5afbbe0d 10603+ h_inode = au_h_iptr(inode, au_ibtop(inode));
b752ccd1 10604+ if (!au_test_nfsd()) {
392086de 10605+ err = au_vdir_fill_de(file, ctx);
9dbd164d 10606+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 10607+ } else {
10608+ /*
10609+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
10610+ * encode_fh() and others.
10611+ */
9dbd164d 10612+ atomic_inc(&h_inode->i_count);
1facf9fc 10613+ di_read_unlock(dentry, AuLock_IR);
10614+ si_read_unlock(sb);
392086de 10615+ err = au_vdir_fill_de(file, ctx);
1facf9fc 10616+ fsstack_copy_attr_atime(inode, h_inode);
10617+ fi_write_unlock(file);
9dbd164d 10618+ iput(h_inode);
1facf9fc 10619+
10620+ AuTraceErr(err);
10621+ return err;
10622+ }
10623+
4f0767ce 10624+out_unlock:
1facf9fc 10625+ di_read_unlock(dentry, AuLock_IR);
10626+ fi_write_unlock(file);
4f0767ce 10627+out:
1facf9fc 10628+ si_read_unlock(sb);
10629+ return err;
10630+}
10631+
10632+/* ---------------------------------------------------------------------- */
10633+
10634+#define AuTestEmpty_WHONLY 1
dece6358
AM
10635+#define AuTestEmpty_CALLED (1 << 1)
10636+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 10637+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
10638+#define au_fset_testempty(flags, name) \
10639+ do { (flags) |= AuTestEmpty_##name; } while (0)
10640+#define au_fclr_testempty(flags, name) \
10641+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 10642+
dece6358
AM
10643+#ifndef CONFIG_AUFS_SHWH
10644+#undef AuTestEmpty_SHWH
10645+#define AuTestEmpty_SHWH 0
10646+#endif
10647+
1facf9fc 10648+struct test_empty_arg {
392086de 10649+ struct dir_context ctx;
1308ab2a 10650+ struct au_nhash *whlist;
1facf9fc 10651+ unsigned int flags;
10652+ int err;
10653+ aufs_bindex_t bindex;
10654+};
10655+
392086de
AM
10656+static int test_empty_cb(struct dir_context *ctx, const char *__name,
10657+ int namelen, loff_t offset __maybe_unused, u64 ino,
dece6358 10658+ unsigned int d_type)
1facf9fc 10659+{
392086de
AM
10660+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
10661+ ctx);
1facf9fc 10662+ char *name = (void *)__name;
10663+
10664+ arg->err = 0;
10665+ au_fset_testempty(arg->flags, CALLED);
10666+ /* smp_mb(); */
10667+ if (name[0] == '.'
10668+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
10669+ goto out; /* success */
10670+
10671+ if (namelen <= AUFS_WH_PFX_LEN
10672+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
10673+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 10674+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10675+ arg->err = -ENOTEMPTY;
10676+ goto out;
10677+ }
10678+
10679+ name += AUFS_WH_PFX_LEN;
10680+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 10681+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10682+ arg->err = au_nhash_append_wh
1308ab2a 10683+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 10684+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 10685+
4f0767ce 10686+out:
1facf9fc 10687+ /* smp_mb(); */
10688+ AuTraceErr(arg->err);
10689+ return arg->err;
10690+}
10691+
10692+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10693+{
10694+ int err;
10695+ struct file *h_file;
acd2b654 10696+ struct au_branch *br;
1facf9fc 10697+
10698+ h_file = au_h_open(dentry, arg->bindex,
10699+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
392086de 10700+ /*file*/NULL, /*force_wr*/0);
1facf9fc 10701+ err = PTR_ERR(h_file);
10702+ if (IS_ERR(h_file))
10703+ goto out;
10704+
10705+ err = 0;
10706+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
c06a8ce3 10707+ && !file_inode(h_file)->i_nlink)
1facf9fc 10708+ goto out_put;
10709+
10710+ do {
10711+ arg->err = 0;
10712+ au_fclr_testempty(arg->flags, CALLED);
10713+ /* smp_mb(); */
392086de 10714+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1facf9fc 10715+ if (err >= 0)
10716+ err = arg->err;
10717+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
10718+
4f0767ce 10719+out_put:
1facf9fc 10720+ fput(h_file);
acd2b654
AM
10721+ br = au_sbr(dentry->d_sb, arg->bindex);
10722+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 10723+out:
1facf9fc 10724+ return err;
10725+}
10726+
10727+struct do_test_empty_args {
10728+ int *errp;
10729+ struct dentry *dentry;
10730+ struct test_empty_arg *arg;
10731+};
10732+
10733+static void call_do_test_empty(void *args)
10734+{
10735+ struct do_test_empty_args *a = args;
10736+ *a->errp = do_test_empty(a->dentry, a->arg);
10737+}
10738+
10739+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10740+{
10741+ int err, wkq_err;
10742+ struct dentry *h_dentry;
10743+ struct inode *h_inode;
10744+
10745+ h_dentry = au_h_dptr(dentry, arg->bindex);
5527c038 10746+ h_inode = d_inode(h_dentry);
53392da6 10747+ /* todo: i_mode changes anytime? */
be118d29 10748+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 10749+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
3c1bdaff 10750+ inode_unlock_shared(h_inode);
1facf9fc 10751+ if (!err)
10752+ err = do_test_empty(dentry, arg);
10753+ else {
10754+ struct do_test_empty_args args = {
10755+ .errp = &err,
10756+ .dentry = dentry,
10757+ .arg = arg
10758+ };
10759+ unsigned int flags = arg->flags;
10760+
10761+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
10762+ if (unlikely(wkq_err))
10763+ err = wkq_err;
10764+ arg->flags = flags;
10765+ }
10766+
10767+ return err;
10768+}
10769+
10770+int au_test_empty_lower(struct dentry *dentry)
10771+{
10772+ int err;
1308ab2a 10773+ unsigned int rdhash;
5afbbe0d 10774+ aufs_bindex_t bindex, btop, btail;
1308ab2a 10775+ struct au_nhash whlist;
392086de
AM
10776+ struct test_empty_arg arg = {
10777+ .ctx = {
2000de60 10778+ .actor = test_empty_cb
392086de
AM
10779+ }
10780+ };
076b876e 10781+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg);
1facf9fc 10782+
dece6358
AM
10783+ SiMustAnyLock(dentry->d_sb);
10784+
1308ab2a 10785+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
10786+ if (!rdhash)
10787+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
10788+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 10789+ if (unlikely(err))
1facf9fc 10790+ goto out;
10791+
1facf9fc 10792+ arg.flags = 0;
1308ab2a 10793+ arg.whlist = &whlist;
5afbbe0d 10794+ btop = au_dbtop(dentry);
dece6358
AM
10795+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10796+ au_fset_testempty(arg.flags, SHWH);
076b876e
AM
10797+ test_empty = do_test_empty;
10798+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1))
10799+ test_empty = sio_test_empty;
5afbbe0d 10800+ arg.bindex = btop;
076b876e 10801+ err = test_empty(dentry, &arg);
1facf9fc 10802+ if (unlikely(err))
10803+ goto out_whlist;
10804+
10805+ au_fset_testempty(arg.flags, WHONLY);
10806+ btail = au_dbtaildir(dentry);
5afbbe0d 10807+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) {
1facf9fc 10808+ struct dentry *h_dentry;
10809+
10810+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10811+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10812+ arg.bindex = bindex;
076b876e 10813+ err = test_empty(dentry, &arg);
1facf9fc 10814+ }
10815+ }
10816+
4f0767ce 10817+out_whlist:
1308ab2a 10818+ au_nhash_wh_free(&whlist);
4f0767ce 10819+out:
1facf9fc 10820+ return err;
10821+}
10822+
10823+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
10824+{
10825+ int err;
392086de
AM
10826+ struct test_empty_arg arg = {
10827+ .ctx = {
2000de60 10828+ .actor = test_empty_cb
392086de
AM
10829+ }
10830+ };
1facf9fc 10831+ aufs_bindex_t bindex, btail;
10832+
10833+ err = 0;
1308ab2a 10834+ arg.whlist = whlist;
1facf9fc 10835+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
10836+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10837+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 10838+ btail = au_dbtaildir(dentry);
5afbbe0d 10839+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) {
1facf9fc 10840+ struct dentry *h_dentry;
10841+
10842+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10843+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10844+ arg.bindex = bindex;
10845+ err = sio_test_empty(dentry, &arg);
10846+ }
10847+ }
10848+
10849+ return err;
10850+}
10851+
10852+/* ---------------------------------------------------------------------- */
10853+
10854+const struct file_operations aufs_dir_fop = {
4a4d8108 10855+ .owner = THIS_MODULE,
027c5e7a 10856+ .llseek = default_llseek,
1facf9fc 10857+ .read = generic_read_dir,
5afbbe0d 10858+ .iterate_shared = aufs_iterate_shared,
1facf9fc 10859+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
10860+#ifdef CONFIG_COMPAT
10861+ .compat_ioctl = aufs_compat_ioctl_dir,
10862+#endif
1facf9fc 10863+ .open = aufs_open_dir,
10864+ .release = aufs_release_dir,
4a4d8108 10865+ .flush = aufs_flush_dir,
1facf9fc 10866+ .fsync = aufs_fsync_dir
10867+};
7f207e10 10868diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
fbc438ed
JR
10869--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 08:00:00.000000000 +0800
10870+++ linux/fs/aufs/dir.h 2019-07-11 21:21:54.379051070 +0800
9f237c51 10871@@ -0,0 +1,134 @@
062440b3 10872+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 10873+/*
ba1aed25 10874+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 10875+ *
10876+ * This program, aufs is free software; you can redistribute it and/or modify
10877+ * it under the terms of the GNU General Public License as published by
10878+ * the Free Software Foundation; either version 2 of the License, or
10879+ * (at your option) any later version.
dece6358
AM
10880+ *
10881+ * This program is distributed in the hope that it will be useful,
10882+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10883+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10884+ * GNU General Public License for more details.
10885+ *
10886+ * You should have received a copy of the GNU General Public License
523b37e3 10887+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10888+ */
10889+
10890+/*
10891+ * directory operations
10892+ */
10893+
10894+#ifndef __AUFS_DIR_H__
10895+#define __AUFS_DIR_H__
10896+
10897+#ifdef __KERNEL__
10898+
10899+#include <linux/fs.h>
1facf9fc 10900+
10901+/* ---------------------------------------------------------------------- */
10902+
10903+/* need to be faster and smaller */
10904+
10905+struct au_nhash {
dece6358
AM
10906+ unsigned int nh_num;
10907+ struct hlist_head *nh_head;
1facf9fc 10908+};
10909+
10910+struct au_vdir_destr {
10911+ unsigned char len;
10912+ unsigned char name[0];
10913+} __packed;
10914+
10915+struct au_vdir_dehstr {
10916+ struct hlist_node hash;
1c60b727 10917+ struct au_vdir_destr *str;
9f237c51 10918+ struct rcu_head rcu;
4a4d8108 10919+} ____cacheline_aligned_in_smp;
1facf9fc 10920+
10921+struct au_vdir_de {
10922+ ino_t de_ino;
10923+ unsigned char de_type;
10924+ /* caution: packed */
10925+ struct au_vdir_destr de_str;
10926+} __packed;
10927+
10928+struct au_vdir_wh {
10929+ struct hlist_node wh_hash;
dece6358
AM
10930+#ifdef CONFIG_AUFS_SHWH
10931+ ino_t wh_ino;
1facf9fc 10932+ aufs_bindex_t wh_bindex;
dece6358
AM
10933+ unsigned char wh_type;
10934+#else
10935+ aufs_bindex_t wh_bindex;
10936+#endif
10937+ /* caution: packed */
1facf9fc 10938+ struct au_vdir_destr wh_str;
10939+} __packed;
10940+
10941+union au_vdir_deblk_p {
10942+ unsigned char *deblk;
10943+ struct au_vdir_de *de;
10944+};
10945+
10946+struct au_vdir {
10947+ unsigned char **vd_deblk;
10948+ unsigned long vd_nblk;
1facf9fc 10949+ struct {
10950+ unsigned long ul;
10951+ union au_vdir_deblk_p p;
10952+ } vd_last;
10953+
be118d29 10954+ u64 vd_version;
dece6358 10955+ unsigned int vd_deblk_sz;
9f237c51
AM
10956+ unsigned long vd_jiffy;
10957+ struct rcu_head rcu;
4a4d8108 10958+} ____cacheline_aligned_in_smp;
1facf9fc 10959+
10960+/* ---------------------------------------------------------------------- */
10961+
10962+/* dir.c */
10963+extern const struct file_operations aufs_dir_fop;
10964+void au_add_nlink(struct inode *dir, struct inode *h_dir);
10965+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 10966+loff_t au_dir_size(struct file *file, struct dentry *dentry);
b912730e 10967+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc);
1facf9fc 10968+int au_test_empty_lower(struct dentry *dentry);
10969+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
10970+
10971+/* vdir.c */
1308ab2a 10972+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
10973+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
10974+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 10975+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
10976+ int limit);
dece6358
AM
10977+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
10978+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
10979+ unsigned int d_type, aufs_bindex_t bindex,
10980+ unsigned char shwh);
1c60b727 10981+void au_vdir_free(struct au_vdir *vdir);
1facf9fc 10982+int au_vdir_init(struct file *file);
392086de 10983+int au_vdir_fill_de(struct file *file, struct dir_context *ctx);
1facf9fc 10984+
10985+/* ioctl.c */
10986+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
10987+
1308ab2a 10988+#ifdef CONFIG_AUFS_RDU
10989+/* rdu.c */
10990+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10991+#ifdef CONFIG_COMPAT
10992+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
10993+ unsigned long arg);
10994+#endif
1308ab2a 10995+#else
c1595e42
JR
10996+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file,
10997+ unsigned int cmd, unsigned long arg)
b752ccd1 10998+#ifdef CONFIG_COMPAT
c1595e42
JR
10999+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file,
11000+ unsigned int cmd, unsigned long arg)
b752ccd1 11001+#endif
1308ab2a 11002+#endif
11003+
1facf9fc 11004+#endif /* __KERNEL__ */
11005+#endif /* __AUFS_DIR_H__ */
8b6a4947 11006diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c
fbc438ed
JR
11007--- /usr/share/empty/fs/aufs/dirren.c 1970-01-01 08:00:00.000000000 +0800
11008+++ linux/fs/aufs/dirren.c 2019-07-11 21:21:54.379051070 +0800
062440b3 11009@@ -0,0 +1,1316 @@
cd7a4cd9 11010+// SPDX-License-Identifier: GPL-2.0
8b6a4947 11011+/*
ba1aed25 11012+ * Copyright (C) 2017-2019 Junjiro R. Okajima
8b6a4947
AM
11013+ *
11014+ * This program, aufs is free software; you can redistribute it and/or modify
11015+ * it under the terms of the GNU General Public License as published by
11016+ * the Free Software Foundation; either version 2 of the License, or
11017+ * (at your option) any later version.
11018+ *
11019+ * This program is distributed in the hope that it will be useful,
11020+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11021+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11022+ * GNU General Public License for more details.
11023+ *
11024+ * You should have received a copy of the GNU General Public License
11025+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
11026+ */
11027+
11028+/*
acd2b654 11029+ * special handling in renaming a directory
8b6a4947
AM
11030+ * in order to support looking-up the before-renamed name on the lower readonly
11031+ * branches
11032+ */
11033+
11034+#include <linux/byteorder/generic.h>
11035+#include "aufs.h"
11036+
11037+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent)
11038+{
11039+ int idx;
11040+
11041+ idx = au_dr_ihash(ent->dr_h_ino);
11042+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx);
11043+}
11044+
11045+static int au_dr_hino_test_empty(struct au_dr_br *dr)
11046+{
11047+ int ret, i;
11048+ struct hlist_bl_head *hbl;
11049+
11050+ ret = 1;
11051+ for (i = 0; ret && i < AuDirren_NHASH; i++) {
11052+ hbl = dr->dr_h_ino + i;
11053+ hlist_bl_lock(hbl);
11054+ ret &= hlist_bl_empty(hbl);
11055+ hlist_bl_unlock(hbl);
11056+ }
11057+
11058+ return ret;
11059+}
11060+
11061+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino)
11062+{
11063+ struct au_dr_hino *found, *ent;
11064+ struct hlist_bl_head *hbl;
11065+ struct hlist_bl_node *pos;
11066+ int idx;
11067+
11068+ found = NULL;
11069+ idx = au_dr_ihash(ino);
11070+ hbl = dr->dr_h_ino + idx;
11071+ hlist_bl_lock(hbl);
11072+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
11073+ if (ent->dr_h_ino == ino) {
11074+ found = ent;
11075+ break;
11076+ }
11077+ hlist_bl_unlock(hbl);
11078+
11079+ return found;
11080+}
11081+
11082+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino,
11083+ struct au_dr_hino *add_ent)
11084+{
11085+ int found, idx;
11086+ struct hlist_bl_head *hbl;
11087+ struct hlist_bl_node *pos;
11088+ struct au_dr_hino *ent;
11089+
11090+ found = 0;
11091+ idx = au_dr_ihash(ino);
11092+ hbl = dr->dr_h_ino + idx;
11093+#if 0
11094+ {
11095+ struct hlist_bl_node *tmp;
11096+
11097+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
11098+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino);
11099+ }
11100+#endif
11101+ hlist_bl_lock(hbl);
11102+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
11103+ if (ent->dr_h_ino == ino) {
11104+ found = 1;
11105+ break;
11106+ }
11107+ if (!found && add_ent)
11108+ hlist_bl_add_head(&add_ent->dr_hnode, hbl);
11109+ hlist_bl_unlock(hbl);
11110+
11111+ if (!found && add_ent)
11112+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino);
11113+
11114+ return found;
11115+}
11116+
11117+void au_dr_hino_free(struct au_dr_br *dr)
11118+{
11119+ int i;
11120+ struct hlist_bl_head *hbl;
11121+ struct hlist_bl_node *pos, *tmp;
11122+ struct au_dr_hino *ent;
11123+
11124+ /* SiMustWriteLock(sb); */
11125+
11126+ for (i = 0; i < AuDirren_NHASH; i++) {
11127+ hbl = dr->dr_h_ino + i;
11128+ /* no spinlock since sbinfo must be write-locked */
11129+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
9f237c51 11130+ au_kfree_rcu(ent);
8b6a4947
AM
11131+ INIT_HLIST_BL_HEAD(hbl);
11132+ }
11133+}
11134+
11135+/* returns the number of inodes or an error */
11136+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br,
11137+ struct file *hinofile)
11138+{
11139+ int err, i;
11140+ ssize_t ssz;
11141+ loff_t pos, oldsize;
11142+ __be64 u64;
11143+ struct inode *hinoinode;
11144+ struct hlist_bl_head *hbl;
11145+ struct hlist_bl_node *n1, *n2;
11146+ struct au_dr_hino *ent;
11147+
11148+ SiMustWriteLock(sb);
11149+ AuDebugOn(!au_br_writable(br->br_perm));
11150+
11151+ hinoinode = file_inode(hinofile);
11152+ oldsize = i_size_read(hinoinode);
11153+
11154+ err = 0;
11155+ pos = 0;
11156+ hbl = br->br_dirren.dr_h_ino;
11157+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) {
11158+ /* no bit-lock since sbinfo must be write-locked */
11159+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) {
11160+ AuDbg("hi%llu, %pD2\n",
11161+ (unsigned long long)ent->dr_h_ino, hinofile);
11162+ u64 = cpu_to_be64(ent->dr_h_ino);
11163+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos);
11164+ if (ssz == sizeof(u64))
11165+ continue;
11166+
11167+ /* write error */
11168+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11169+ err = -ENOSPC;
11170+ if (ssz < 0)
11171+ err = ssz;
11172+ break;
11173+ }
11174+ }
11175+ /* regardless the error */
11176+ if (pos < oldsize) {
11177+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile);
11178+ AuTraceErr(err);
11179+ }
11180+
11181+ AuTraceErr(err);
11182+ return err;
11183+}
11184+
11185+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile)
11186+{
11187+ int err, hidx;
11188+ ssize_t ssz;
11189+ size_t sz, n;
11190+ loff_t pos;
11191+ uint64_t u64;
11192+ struct au_dr_hino *ent;
11193+ struct inode *hinoinode;
11194+ struct hlist_bl_head *hbl;
11195+
11196+ err = 0;
11197+ pos = 0;
11198+ hbl = dr->dr_h_ino;
11199+ hinoinode = file_inode(hinofile);
11200+ sz = i_size_read(hinoinode);
11201+ AuDebugOn(sz % sizeof(u64));
11202+ n = sz / sizeof(u64);
11203+ while (n--) {
11204+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos);
11205+ if (unlikely(ssz != sizeof(u64))) {
11206+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11207+ err = -EINVAL;
11208+ if (ssz < 0)
11209+ err = ssz;
11210+ goto out_free;
11211+ }
11212+
11213+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11214+ if (!ent) {
11215+ err = -ENOMEM;
11216+ AuTraceErr(err);
11217+ goto out_free;
11218+ }
11219+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64);
11220+ AuDbg("hi%llu, %pD2\n",
11221+ (unsigned long long)ent->dr_h_ino, hinofile);
11222+ hidx = au_dr_ihash(ent->dr_h_ino);
11223+ au_hbl_add(&ent->dr_hnode, hbl + hidx);
11224+ }
11225+ goto out; /* success */
11226+
11227+out_free:
11228+ au_dr_hino_free(dr);
11229+out:
11230+ AuTraceErr(err);
11231+ return err;
11232+}
11233+
11234+/*
11235+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not.
11236+ * @path is a switch to distinguish load and store.
11237+ */
11238+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
11239+ struct au_branch *br, const struct path *path)
11240+{
11241+ int err, flags;
11242+ unsigned char load, suspend;
11243+ struct file *hinofile;
11244+ struct au_hinode *hdir;
11245+ struct inode *dir, *delegated;
11246+ struct path hinopath;
11247+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO,
11248+ sizeof(AUFS_WH_DR_BRHINO) - 1);
11249+
11250+ AuDebugOn(bindex < 0 && !br);
11251+ AuDebugOn(bindex >= 0 && br);
11252+
11253+ err = -EINVAL;
11254+ suspend = !br;
11255+ if (suspend)
11256+ br = au_sbr(sb, bindex);
11257+ load = !!path;
11258+ if (!load) {
11259+ path = &br->br_path;
11260+ AuDebugOn(!au_br_writable(br->br_perm));
11261+ if (unlikely(!au_br_writable(br->br_perm)))
11262+ goto out;
11263+ }
11264+
11265+ hdir = NULL;
11266+ if (suspend) {
11267+ dir = d_inode(sb->s_root);
11268+ hdir = au_hinode(au_ii(dir), bindex);
11269+ dir = hdir->hi_inode;
11270+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11271+ } else {
11272+ dir = d_inode(path->dentry);
11273+ inode_lock_nested(dir, AuLsc_I_CHILD);
11274+ }
11275+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry);
11276+ err = PTR_ERR(hinopath.dentry);
11277+ if (IS_ERR(hinopath.dentry))
11278+ goto out_unlock;
11279+
11280+ err = 0;
11281+ flags = O_RDONLY;
11282+ if (load) {
11283+ if (d_is_negative(hinopath.dentry))
11284+ goto out_dput; /* success */
11285+ } else {
11286+ if (au_dr_hino_test_empty(&br->br_dirren)) {
11287+ if (d_is_positive(hinopath.dentry)) {
11288+ delegated = NULL;
11289+ err = vfsub_unlink(dir, &hinopath, &delegated,
11290+ /*force*/0);
11291+ AuTraceErr(err);
11292+ if (unlikely(err))
11293+ pr_err("ignored err %d, %pd2\n",
11294+ err, hinopath.dentry);
11295+ if (unlikely(err == -EWOULDBLOCK))
11296+ iput(delegated);
11297+ err = 0;
11298+ }
11299+ goto out_dput;
11300+ } else if (!d_is_positive(hinopath.dentry)) {
11301+ err = vfsub_create(dir, &hinopath, 0600,
11302+ /*want_excl*/false);
11303+ AuTraceErr(err);
11304+ if (unlikely(err))
11305+ goto out_dput;
11306+ }
11307+ flags = O_WRONLY;
11308+ }
11309+ hinopath.mnt = path->mnt;
11310+ hinofile = vfsub_dentry_open(&hinopath, flags);
11311+ if (suspend)
11312+ au_hn_inode_unlock(hdir);
11313+ else
11314+ inode_unlock(dir);
11315+ dput(hinopath.dentry);
11316+ AuTraceErrPtr(hinofile);
11317+ if (IS_ERR(hinofile)) {
11318+ err = PTR_ERR(hinofile);
11319+ goto out;
11320+ }
11321+
11322+ if (load)
11323+ err = au_dr_hino_load(&br->br_dirren, hinofile);
11324+ else
11325+ err = au_dr_hino_store(sb, br, hinofile);
11326+ fput(hinofile);
11327+ goto out;
11328+
11329+out_dput:
11330+ dput(hinopath.dentry);
11331+out_unlock:
11332+ if (suspend)
11333+ au_hn_inode_unlock(hdir);
11334+ else
11335+ inode_unlock(dir);
11336+out:
11337+ AuTraceErr(err);
11338+ return err;
11339+}
11340+
11341+/* ---------------------------------------------------------------------- */
11342+
11343+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path)
11344+{
11345+ int err;
11346+ struct kstatfs kstfs;
11347+ dev_t dev;
11348+ struct dentry *dentry;
11349+ struct super_block *sb;
11350+
11351+ err = vfs_statfs((void *)path, &kstfs);
11352+ AuTraceErr(err);
11353+ if (unlikely(err))
11354+ goto out;
11355+
11356+ /* todo: support for UUID */
11357+
11358+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) {
11359+ brid->type = AuBrid_FSID;
11360+ brid->fsid = kstfs.f_fsid;
11361+ } else {
11362+ dentry = path->dentry;
11363+ sb = dentry->d_sb;
11364+ dev = sb->s_dev;
11365+ if (dev) {
11366+ brid->type = AuBrid_DEV;
11367+ brid->dev = dev;
11368+ }
11369+ }
11370+
11371+out:
11372+ return err;
11373+}
11374+
11375+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
11376+ const struct path *path)
11377+{
11378+ int err, i;
11379+ struct au_dr_br *dr;
11380+ struct hlist_bl_head *hbl;
11381+
11382+ dr = &br->br_dirren;
11383+ hbl = dr->dr_h_ino;
11384+ for (i = 0; i < AuDirren_NHASH; i++, hbl++)
11385+ INIT_HLIST_BL_HEAD(hbl);
11386+
11387+ err = au_dr_brid_init(&dr->dr_brid, path);
11388+ if (unlikely(err))
11389+ goto out;
11390+
11391+ if (au_opt_test(au_mntflags(sb), DIRREN))
11392+ err = au_dr_hino(sb, /*bindex*/-1, br, path);
11393+
11394+out:
11395+ AuTraceErr(err);
11396+ return err;
11397+}
11398+
11399+int au_dr_br_fin(struct super_block *sb, struct au_branch *br)
11400+{
11401+ int err;
11402+
11403+ err = 0;
11404+ if (au_br_writable(br->br_perm))
11405+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL);
11406+ if (!err)
11407+ au_dr_hino_free(&br->br_dirren);
11408+
11409+ return err;
11410+}
11411+
11412+/* ---------------------------------------------------------------------- */
11413+
11414+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode,
11415+ char *buf, size_t sz)
11416+{
11417+ int err;
11418+ unsigned int major, minor;
11419+ char *p;
11420+
11421+ p = buf;
11422+ err = snprintf(p, sz, "%d_", brid->type);
11423+ AuDebugOn(err > sz);
11424+ p += err;
11425+ sz -= err;
11426+ switch (brid->type) {
11427+ case AuBrid_Unset:
11428+ return -EINVAL;
11429+ case AuBrid_UUID:
11430+ err = snprintf(p, sz, "%pU", brid->uuid.b);
11431+ break;
11432+ case AuBrid_FSID:
11433+ err = snprintf(p, sz, "%08x-%08x",
11434+ brid->fsid.val[0], brid->fsid.val[1]);
11435+ break;
11436+ case AuBrid_DEV:
11437+ major = MAJOR(brid->dev);
11438+ minor = MINOR(brid->dev);
11439+ if (major <= 0xff && minor <= 0xff)
11440+ err = snprintf(p, sz, "%02x%02x", major, minor);
11441+ else
11442+ err = snprintf(p, sz, "%03x:%05x", major, minor);
11443+ break;
11444+ }
11445+ AuDebugOn(err > sz);
11446+ p += err;
11447+ sz -= err;
11448+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino);
11449+ AuDebugOn(err > sz);
11450+ p += err;
11451+ sz -= err;
11452+
11453+ return p - buf;
11454+}
11455+
11456+static int au_drinfo_name(struct au_branch *br, char *name, int len)
11457+{
11458+ int rlen;
11459+ struct dentry *br_dentry;
11460+ struct inode *br_inode;
11461+
11462+ br_dentry = au_br_dentry(br);
11463+ br_inode = d_inode(br_dentry);
11464+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len);
11465+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ);
11466+ AuDebugOn(rlen > len);
11467+
11468+ return rlen;
11469+}
11470+
11471+/* ---------------------------------------------------------------------- */
11472+
11473+/*
11474+ * from the given @h_dentry, construct drinfo at @*fdata.
11475+ * when the size of @*fdata is not enough, reallocate and return new @fdata and
11476+ * @allocated.
11477+ */
11478+static int au_drinfo_construct(struct au_drinfo_fdata **fdata,
11479+ struct dentry *h_dentry,
11480+ unsigned char *allocated)
11481+{
11482+ int err, v;
11483+ struct au_drinfo_fdata *f, *p;
11484+ struct au_drinfo *drinfo;
11485+ struct inode *h_inode;
11486+ struct qstr *qname;
11487+
11488+ err = 0;
11489+ f = *fdata;
11490+ h_inode = d_inode(h_dentry);
11491+ qname = &h_dentry->d_name;
11492+ drinfo = &f->drinfo;
11493+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino);
11494+ drinfo->oldnamelen = qname->len;
11495+ if (*allocated < sizeof(*f) + qname->len) {
11496+ v = roundup_pow_of_two(*allocated + qname->len);
11497+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0);
11498+ if (unlikely(!p)) {
11499+ err = -ENOMEM;
11500+ AuTraceErr(err);
11501+ goto out;
11502+ }
11503+ f = p;
11504+ *fdata = f;
11505+ *allocated = v;
11506+ drinfo = &f->drinfo;
11507+ }
11508+ memcpy(drinfo->oldname, qname->name, qname->len);
11509+ AuDbg("i%llu, %.*s\n",
11510+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen,
11511+ drinfo->oldname);
11512+
11513+out:
11514+ AuTraceErr(err);
11515+ return err;
11516+}
11517+
11518+/* callers have to free the return value */
11519+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino)
11520+{
11521+ struct au_drinfo *ret, *drinfo;
11522+ struct au_drinfo_fdata fdata;
11523+ int len;
11524+ loff_t pos;
11525+ ssize_t ssz;
11526+
11527+ ret = ERR_PTR(-EIO);
11528+ pos = 0;
11529+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos);
11530+ if (unlikely(ssz != sizeof(fdata))) {
11531+ AuIOErr("ssz %zd, %u, %pD2\n",
11532+ ssz, (unsigned int)sizeof(fdata), file);
11533+ goto out;
11534+ }
11535+
11536+ fdata.magic = ntohl((__force __be32)fdata.magic);
11537+ switch (fdata.magic) {
11538+ case AUFS_DRINFO_MAGIC_V1:
11539+ break;
11540+ default:
11541+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n",
11542+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file);
11543+ goto out;
11544+ }
11545+
11546+ drinfo = &fdata.drinfo;
11547+ len = drinfo->oldnamelen;
11548+ if (!len) {
11549+ AuIOErr("broken drinfo %pD2\n", file);
11550+ goto out;
11551+ }
11552+
11553+ ret = NULL;
11554+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino);
11555+ if (unlikely(h_ino && drinfo->ino != h_ino)) {
11556+ AuDbg("ignored i%llu, i%llu, %pD2\n",
11557+ (unsigned long long)drinfo->ino,
11558+ (unsigned long long)h_ino, file);
11559+ goto out; /* success */
11560+ }
11561+
11562+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS);
11563+ if (unlikely(!ret)) {
11564+ ret = ERR_PTR(-ENOMEM);
11565+ AuTraceErrPtr(ret);
11566+ goto out;
11567+ }
11568+
11569+ *ret = *drinfo;
11570+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos);
11571+ if (unlikely(ssz != len)) {
9f237c51 11572+ au_kfree_rcu(ret);
8b6a4947
AM
11573+ ret = ERR_PTR(-EIO);
11574+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file);
11575+ goto out;
11576+ }
11577+
11578+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname);
11579+
11580+out:
11581+ return ret;
11582+}
11583+
11584+/* ---------------------------------------------------------------------- */
11585+
11586+/* in order to be revertible */
11587+struct au_drinfo_rev_elm {
11588+ int created;
11589+ struct dentry *info_dentry;
11590+ struct au_drinfo *info_last;
11591+};
11592+
11593+struct au_drinfo_rev {
11594+ unsigned char already;
11595+ aufs_bindex_t nelm;
11596+ struct au_drinfo_rev_elm elm[0];
11597+};
11598+
11599+/* todo: isn't it too large? */
11600+struct au_drinfo_store {
11601+ struct path h_ppath;
11602+ struct dentry *h_dentry;
11603+ struct au_drinfo_fdata *fdata;
11604+ char *infoname; /* inside of whname, just after PFX */
11605+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ];
11606+ aufs_bindex_t btgt, btail;
11607+ unsigned char no_sio,
11608+ allocated, /* current size of *fdata */
11609+ infonamelen, /* room size for p */
acd2b654 11610+ whnamelen, /* length of the generated name */
8b6a4947
AM
11611+ renameback; /* renamed back */
11612+};
11613+
11614+/* on rename(2) error, the caller should revert it using @elm */
11615+static int au_drinfo_do_store(struct au_drinfo_store *w,
11616+ struct au_drinfo_rev_elm *elm)
11617+{
11618+ int err, len;
11619+ ssize_t ssz;
11620+ loff_t pos;
11621+ struct path infopath = {
11622+ .mnt = w->h_ppath.mnt
11623+ };
11624+ struct inode *h_dir, *h_inode, *delegated;
11625+ struct file *infofile;
11626+ struct qstr *qname;
11627+
11628+ AuDebugOn(elm
11629+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm)));
11630+
11631+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry,
11632+ w->whnamelen);
11633+ AuTraceErrPtr(infopath.dentry);
11634+ if (IS_ERR(infopath.dentry)) {
11635+ err = PTR_ERR(infopath.dentry);
11636+ goto out;
11637+ }
11638+
11639+ err = 0;
11640+ h_dir = d_inode(w->h_ppath.dentry);
11641+ if (elm && d_is_negative(infopath.dentry)) {
11642+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true);
11643+ AuTraceErr(err);
11644+ if (unlikely(err))
11645+ goto out_dput;
11646+ elm->created = 1;
11647+ elm->info_dentry = dget(infopath.dentry);
11648+ }
11649+
11650+ infofile = vfsub_dentry_open(&infopath, O_RDWR);
11651+ AuTraceErrPtr(infofile);
11652+ if (IS_ERR(infofile)) {
11653+ err = PTR_ERR(infofile);
11654+ goto out_dput;
11655+ }
11656+
11657+ h_inode = d_inode(infopath.dentry);
11658+ if (elm && i_size_read(h_inode)) {
11659+ h_inode = d_inode(w->h_dentry);
11660+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino);
11661+ AuTraceErrPtr(elm->info_last);
11662+ if (IS_ERR(elm->info_last)) {
11663+ err = PTR_ERR(elm->info_last);
11664+ elm->info_last = NULL;
11665+ AuDebugOn(elm->info_dentry);
11666+ goto out_fput;
11667+ }
11668+ }
11669+
11670+ if (elm && w->renameback) {
11671+ delegated = NULL;
11672+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0);
11673+ AuTraceErr(err);
11674+ if (unlikely(err == -EWOULDBLOCK))
11675+ iput(delegated);
11676+ goto out_fput;
11677+ }
11678+
11679+ pos = 0;
11680+ qname = &w->h_dentry->d_name;
11681+ len = sizeof(*w->fdata) + qname->len;
11682+ if (!elm)
11683+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen;
11684+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos);
11685+ if (ssz == len) {
11686+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino,
11687+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname);
11688+ goto out_fput; /* success */
11689+ } else {
11690+ err = -EIO;
11691+ if (ssz < 0)
11692+ err = ssz;
11693+ /* the caller should revert it using @elm */
11694+ }
11695+
11696+out_fput:
11697+ fput(infofile);
11698+out_dput:
11699+ dput(infopath.dentry);
11700+out:
11701+ AuTraceErr(err);
11702+ return err;
11703+}
11704+
11705+struct au_call_drinfo_do_store_args {
11706+ int *errp;
11707+ struct au_drinfo_store *w;
11708+ struct au_drinfo_rev_elm *elm;
11709+};
11710+
11711+static void au_call_drinfo_do_store(void *args)
11712+{
11713+ struct au_call_drinfo_do_store_args *a = args;
11714+
11715+ *a->errp = au_drinfo_do_store(a->w, a->elm);
11716+}
11717+
11718+static int au_drinfo_store_sio(struct au_drinfo_store *w,
11719+ struct au_drinfo_rev_elm *elm)
11720+{
11721+ int err, wkq_err;
11722+
11723+ if (w->no_sio)
11724+ err = au_drinfo_do_store(w, elm);
11725+ else {
11726+ struct au_call_drinfo_do_store_args a = {
11727+ .errp = &err,
11728+ .w = w,
11729+ .elm = elm
11730+ };
11731+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a);
11732+ if (unlikely(wkq_err))
11733+ err = wkq_err;
11734+ }
11735+ AuTraceErr(err);
11736+
11737+ return err;
11738+}
11739+
11740+static int au_drinfo_store_work_init(struct au_drinfo_store *w,
11741+ aufs_bindex_t btgt)
11742+{
11743+ int err;
11744+
11745+ memset(w, 0, sizeof(*w));
11746+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40);
11747+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX);
11748+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11749+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX);
11750+ w->btgt = btgt;
11751+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
11752+
11753+ err = -ENOMEM;
11754+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS);
11755+ if (unlikely(!w->fdata)) {
11756+ AuTraceErr(err);
11757+ goto out;
11758+ }
11759+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1);
11760+ err = 0;
11761+
11762+out:
11763+ return err;
11764+}
11765+
11766+static void au_drinfo_store_work_fin(struct au_drinfo_store *w)
11767+{
9f237c51 11768+ au_kfree_rcu(w->fdata);
8b6a4947
AM
11769+}
11770+
11771+static void au_drinfo_store_rev(struct au_drinfo_rev *rev,
11772+ struct au_drinfo_store *w)
11773+{
11774+ struct au_drinfo_rev_elm *elm;
11775+ struct inode *h_dir, *delegated;
11776+ int err, nelm;
11777+ struct path infopath = {
11778+ .mnt = w->h_ppath.mnt
11779+ };
11780+
11781+ h_dir = d_inode(w->h_ppath.dentry);
11782+ IMustLock(h_dir);
11783+
11784+ err = 0;
11785+ elm = rev->elm;
11786+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11787+ AuDebugOn(elm->created && elm->info_last);
11788+ if (elm->created) {
11789+ AuDbg("here\n");
11790+ delegated = NULL;
11791+ infopath.dentry = elm->info_dentry;
11792+ err = vfsub_unlink(h_dir, &infopath, &delegated,
11793+ !w->no_sio);
11794+ AuTraceErr(err);
11795+ if (unlikely(err == -EWOULDBLOCK))
11796+ iput(delegated);
11797+ dput(elm->info_dentry);
11798+ } else if (elm->info_last) {
11799+ AuDbg("here\n");
11800+ w->fdata->drinfo = *elm->info_last;
11801+ memcpy(w->fdata->drinfo.oldname,
11802+ elm->info_last->oldname,
11803+ elm->info_last->oldnamelen);
11804+ err = au_drinfo_store_sio(w, /*elm*/NULL);
9f237c51 11805+ au_kfree_rcu(elm->info_last);
8b6a4947
AM
11806+ }
11807+ if (unlikely(err))
11808+ AuIOErr("%d, %s\n", err, w->whname);
11809+ /* go on even if err */
11810+ }
11811+}
11812+
11813+/* caller has to call au_dr_rename_fin() later */
11814+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt,
11815+ struct qstr *dst_name, void *_rev)
11816+{
11817+ int err, sz, nelm;
11818+ aufs_bindex_t bindex, btail;
11819+ struct au_drinfo_store work;
11820+ struct au_drinfo_rev *rev, **p;
11821+ struct au_drinfo_rev_elm *elm;
11822+ struct super_block *sb;
11823+ struct au_branch *br;
11824+ struct au_hinode *hdir;
11825+
11826+ err = au_drinfo_store_work_init(&work, btgt);
11827+ AuTraceErr(err);
11828+ if (unlikely(err))
11829+ goto out;
11830+
11831+ err = -ENOMEM;
11832+ btail = au_dbtaildir(dentry);
11833+ nelm = btail - btgt;
11834+ sz = sizeof(*rev) + sizeof(*elm) * nelm;
11835+ rev = kcalloc(1, sz, GFP_NOFS);
11836+ if (unlikely(!rev)) {
11837+ AuTraceErr(err);
11838+ goto out_args;
11839+ }
11840+ rev->nelm = nelm;
11841+ elm = rev->elm;
11842+ p = _rev;
11843+ *p = rev;
11844+
11845+ err = 0;
11846+ sb = dentry->d_sb;
11847+ work.h_ppath.dentry = au_h_dptr(dentry, btgt);
11848+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt);
11849+ hdir = au_hi(d_inode(dentry), btgt);
11850+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11851+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) {
11852+ work.h_dentry = au_h_dptr(dentry, bindex);
11853+ if (!work.h_dentry)
11854+ continue;
11855+
11856+ err = au_drinfo_construct(&work.fdata, work.h_dentry,
11857+ &work.allocated);
11858+ AuTraceErr(err);
11859+ if (unlikely(err))
11860+ break;
11861+
11862+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name);
11863+ br = au_sbr(sb, bindex);
11864+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11865+ work.whnamelen += au_drinfo_name(br, work.infoname,
11866+ work.infonamelen);
11867+ AuDbg("whname %.*s, i%llu, %.*s\n",
11868+ work.whnamelen, work.whname,
11869+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino),
11870+ work.fdata->drinfo.oldnamelen,
11871+ work.fdata->drinfo.oldname);
11872+
11873+ err = au_drinfo_store_sio(&work, elm);
11874+ AuTraceErr(err);
11875+ if (unlikely(err))
11876+ break;
11877+ }
11878+ if (unlikely(err)) {
11879+ /* revert all drinfo */
11880+ au_drinfo_store_rev(rev, &work);
9f237c51 11881+ au_kfree_try_rcu(rev);
8b6a4947
AM
11882+ *p = NULL;
11883+ }
11884+ au_hn_inode_unlock(hdir);
11885+
11886+out_args:
11887+ au_drinfo_store_work_fin(&work);
11888+out:
11889+ return err;
11890+}
11891+
11892+/* ---------------------------------------------------------------------- */
11893+
11894+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
11895+ struct qstr *dst_name, void *_rev)
11896+{
11897+ int err, already;
11898+ ino_t ino;
11899+ struct super_block *sb;
11900+ struct au_branch *br;
11901+ struct au_dr_br *dr;
11902+ struct dentry *h_dentry;
11903+ struct inode *h_inode;
11904+ struct au_dr_hino *ent;
11905+ struct au_drinfo_rev *rev, **p;
11906+
11907+ AuDbg("bindex %d\n", bindex);
11908+
11909+ err = -ENOMEM;
11910+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11911+ if (unlikely(!ent))
11912+ goto out;
11913+
11914+ sb = src->d_sb;
11915+ br = au_sbr(sb, bindex);
11916+ dr = &br->br_dirren;
11917+ h_dentry = au_h_dptr(src, bindex);
11918+ h_inode = d_inode(h_dentry);
11919+ ino = h_inode->i_ino;
11920+ ent->dr_h_ino = ino;
11921+ already = au_dr_hino_test_add(dr, ino, ent);
11922+ AuDbg("b%d, hi%llu, already %d\n",
11923+ bindex, (unsigned long long)ino, already);
11924+
11925+ err = au_drinfo_store(src, bindex, dst_name, _rev);
11926+ AuTraceErr(err);
11927+ if (!err) {
11928+ p = _rev;
11929+ rev = *p;
11930+ rev->already = already;
11931+ goto out; /* success */
11932+ }
11933+
11934+ /* revert */
11935+ if (!already)
11936+ au_dr_hino_del(dr, ent);
9f237c51 11937+ au_kfree_rcu(ent);
8b6a4947
AM
11938+
11939+out:
11940+ AuTraceErr(err);
11941+ return err;
11942+}
11943+
11944+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11945+{
11946+ struct au_drinfo_rev *rev;
11947+ struct au_drinfo_rev_elm *elm;
11948+ int nelm;
11949+
11950+ rev = _rev;
11951+ elm = rev->elm;
11952+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11953+ dput(elm->info_dentry);
9f237c51 11954+ au_kfree_rcu(elm->info_last);
8b6a4947 11955+ }
9f237c51 11956+ au_kfree_try_rcu(rev);
8b6a4947
AM
11957+}
11958+
11959+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11960+{
11961+ int err;
11962+ struct au_drinfo_store work;
11963+ struct au_drinfo_rev *rev = _rev;
11964+ struct super_block *sb;
11965+ struct au_branch *br;
11966+ struct inode *h_inode;
11967+ struct au_dr_br *dr;
11968+ struct au_dr_hino *ent;
11969+
11970+ err = au_drinfo_store_work_init(&work, btgt);
11971+ if (unlikely(err))
11972+ goto out;
11973+
11974+ sb = src->d_sb;
11975+ br = au_sbr(sb, btgt);
11976+ work.h_ppath.dentry = au_h_dptr(src, btgt);
11977+ work.h_ppath.mnt = au_br_mnt(br);
11978+ au_drinfo_store_rev(rev, &work);
11979+ au_drinfo_store_work_fin(&work);
11980+ if (rev->already)
11981+ goto out;
11982+
11983+ dr = &br->br_dirren;
11984+ h_inode = d_inode(work.h_ppath.dentry);
11985+ ent = au_dr_hino_find(dr, h_inode->i_ino);
11986+ BUG_ON(!ent);
11987+ au_dr_hino_del(dr, ent);
9f237c51 11988+ au_kfree_rcu(ent);
8b6a4947
AM
11989+
11990+out:
9f237c51 11991+ au_kfree_try_rcu(rev);
8b6a4947
AM
11992+ if (unlikely(err))
11993+ pr_err("failed to remove dirren info\n");
11994+}
11995+
11996+/* ---------------------------------------------------------------------- */
11997+
11998+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath,
11999+ char *whname, int whnamelen,
12000+ struct dentry **info_dentry)
12001+{
12002+ struct au_drinfo *drinfo;
12003+ struct file *f;
12004+ struct inode *h_dir;
12005+ struct path infopath;
12006+ int unlocked;
12007+
12008+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname);
12009+
12010+ *info_dentry = NULL;
12011+ drinfo = NULL;
12012+ unlocked = 0;
12013+ h_dir = d_inode(h_ppath->dentry);
be118d29 12014+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947
AM
12015+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry,
12016+ whnamelen);
12017+ if (IS_ERR(infopath.dentry)) {
12018+ drinfo = (void *)infopath.dentry;
12019+ goto out;
12020+ }
12021+
12022+ if (d_is_negative(infopath.dentry))
12023+ goto out_dput; /* success */
12024+
12025+ infopath.mnt = h_ppath->mnt;
12026+ f = vfsub_dentry_open(&infopath, O_RDONLY);
12027+ inode_unlock_shared(h_dir);
12028+ unlocked = 1;
12029+ if (IS_ERR(f)) {
12030+ drinfo = (void *)f;
12031+ goto out_dput;
12032+ }
12033+
12034+ drinfo = au_drinfo_read_k(f, /*h_ino*/0);
12035+ if (IS_ERR_OR_NULL(drinfo))
12036+ goto out_fput;
12037+
12038+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname);
12039+ *info_dentry = dget(infopath.dentry); /* keep it alive */
12040+
12041+out_fput:
12042+ fput(f);
12043+out_dput:
12044+ dput(infopath.dentry);
12045+out:
12046+ if (!unlocked)
12047+ inode_unlock_shared(h_dir);
12048+ AuTraceErrPtr(drinfo);
12049+ return drinfo;
12050+}
12051+
12052+struct au_drinfo_do_load_args {
12053+ struct au_drinfo **drinfop;
12054+ struct path *h_ppath;
12055+ char *whname;
12056+ int whnamelen;
12057+ struct dentry **info_dentry;
12058+};
12059+
12060+static void au_call_drinfo_do_load(void *args)
12061+{
12062+ struct au_drinfo_do_load_args *a = args;
12063+
12064+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen,
12065+ a->info_dentry);
12066+}
12067+
12068+struct au_drinfo_load {
12069+ struct path h_ppath;
12070+ struct qstr *qname;
12071+ unsigned char no_sio;
12072+
12073+ aufs_bindex_t ninfo;
12074+ struct au_drinfo **drinfo;
12075+};
12076+
12077+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex,
12078+ struct au_branch *br)
12079+{
12080+ int err, wkq_err, whnamelen, e;
12081+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]
12082+ = AUFS_WH_DR_INFO_PFX;
12083+ struct au_drinfo *drinfo;
12084+ struct qstr oldname;
12085+ struct inode *h_dir, *delegated;
12086+ struct dentry *info_dentry;
12087+ struct path infopath;
12088+
12089+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
12090+ whnamelen += au_drinfo_name(br, whname + whnamelen,
12091+ sizeof(whname) - whnamelen);
12092+ if (w->no_sio)
12093+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen,
12094+ &info_dentry);
12095+ else {
12096+ struct au_drinfo_do_load_args args = {
12097+ .drinfop = &drinfo,
12098+ .h_ppath = &w->h_ppath,
12099+ .whname = whname,
12100+ .whnamelen = whnamelen,
12101+ .info_dentry = &info_dentry
12102+ };
12103+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args);
12104+ if (unlikely(wkq_err))
12105+ drinfo = ERR_PTR(wkq_err);
12106+ }
12107+ err = PTR_ERR(drinfo);
12108+ if (IS_ERR_OR_NULL(drinfo))
12109+ goto out;
12110+
12111+ err = 0;
12112+ oldname.len = drinfo->oldnamelen;
12113+ oldname.name = drinfo->oldname;
12114+ if (au_qstreq(w->qname, &oldname)) {
12115+ /* the name is renamed back */
9f237c51 12116+ au_kfree_rcu(drinfo);
8b6a4947
AM
12117+ drinfo = NULL;
12118+
12119+ infopath.dentry = info_dentry;
12120+ infopath.mnt = w->h_ppath.mnt;
12121+ h_dir = d_inode(w->h_ppath.dentry);
12122+ delegated = NULL;
12123+ inode_lock_nested(h_dir, AuLsc_I_PARENT);
12124+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio);
12125+ inode_unlock(h_dir);
12126+ if (unlikely(e))
12127+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry);
12128+ if (unlikely(e == -EWOULDBLOCK))
12129+ iput(delegated);
12130+ }
9f237c51 12131+ au_kfree_rcu(w->drinfo[bindex]);
8b6a4947
AM
12132+ w->drinfo[bindex] = drinfo;
12133+ dput(info_dentry);
12134+
12135+out:
12136+ AuTraceErr(err);
12137+ return err;
12138+}
12139+
12140+/* ---------------------------------------------------------------------- */
12141+
12142+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n)
12143+{
12144+ struct au_drinfo **p = drinfo;
12145+
12146+ while (n-- > 0)
9f237c51
AM
12147+ au_kfree_rcu(*drinfo++);
12148+ au_kfree_try_rcu(p);
8b6a4947
AM
12149+}
12150+
12151+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12152+ aufs_bindex_t btgt)
12153+{
12154+ int err, ninfo;
12155+ struct au_drinfo_load w;
12156+ aufs_bindex_t bindex, bbot;
12157+ struct au_branch *br;
12158+ struct inode *h_dir;
12159+ struct au_dr_hino *ent;
12160+ struct super_block *sb;
12161+
12162+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n",
12163+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name),
12164+ AuLNPair(&lkup->whname), btgt);
12165+
12166+ sb = dentry->d_sb;
12167+ bbot = au_sbbot(sb);
12168+ w.ninfo = bbot + 1;
12169+ if (!lkup->dirren.drinfo) {
12170+ lkup->dirren.drinfo = kcalloc(w.ninfo,
12171+ sizeof(*lkup->dirren.drinfo),
12172+ GFP_NOFS);
12173+ if (unlikely(!lkup->dirren.drinfo)) {
12174+ err = -ENOMEM;
12175+ goto out;
12176+ }
12177+ lkup->dirren.ninfo = w.ninfo;
12178+ }
12179+ w.drinfo = lkup->dirren.drinfo;
12180+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
12181+ w.h_ppath.dentry = au_h_dptr(dentry, btgt);
12182+ AuDebugOn(!w.h_ppath.dentry);
12183+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt);
12184+ w.qname = &dentry->d_name;
12185+
12186+ ninfo = 0;
12187+ for (bindex = btgt + 1; bindex <= bbot; bindex++) {
12188+ br = au_sbr(sb, bindex);
12189+ err = au_drinfo_load(&w, bindex, br);
12190+ if (unlikely(err))
12191+ goto out_free;
12192+ if (w.drinfo[bindex])
12193+ ninfo++;
12194+ }
12195+ if (!ninfo) {
12196+ br = au_sbr(sb, btgt);
12197+ h_dir = d_inode(w.h_ppath.dentry);
12198+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino);
12199+ AuDebugOn(!ent);
12200+ au_dr_hino_del(&br->br_dirren, ent);
9f237c51 12201+ au_kfree_rcu(ent);
8b6a4947
AM
12202+ }
12203+ goto out; /* success */
12204+
12205+out_free:
12206+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12207+ lkup->dirren.ninfo = 0;
12208+ lkup->dirren.drinfo = NULL;
12209+out:
12210+ AuTraceErr(err);
12211+ return err;
12212+}
12213+
12214+void au_dr_lkup_fin(struct au_do_lookup_args *lkup)
12215+{
12216+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12217+}
12218+
12219+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt)
12220+{
12221+ int err;
12222+ struct au_drinfo *drinfo;
12223+
12224+ err = 0;
12225+ if (!lkup->dirren.drinfo)
12226+ goto out;
12227+ AuDebugOn(lkup->dirren.ninfo < btgt + 1);
12228+ drinfo = lkup->dirren.drinfo[btgt + 1];
12229+ if (!drinfo)
12230+ goto out;
12231+
9f237c51 12232+ au_kfree_try_rcu(lkup->whname.name);
8b6a4947
AM
12233+ lkup->whname.name = NULL;
12234+ lkup->dirren.dr_name.len = drinfo->oldnamelen;
12235+ lkup->dirren.dr_name.name = drinfo->oldname;
12236+ lkup->name = &lkup->dirren.dr_name;
12237+ err = au_wh_name_alloc(&lkup->whname, lkup->name);
12238+ if (!err)
12239+ AuDbg("name %.*s, whname %.*s, b%d\n",
12240+ AuLNPair(lkup->name), AuLNPair(&lkup->whname),
12241+ btgt);
12242+
12243+out:
12244+ AuTraceErr(err);
12245+ return err;
12246+}
12247+
12248+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12249+ ino_t h_ino)
12250+{
12251+ int match;
12252+ struct au_drinfo *drinfo;
12253+
12254+ match = 1;
12255+ if (!lkup->dirren.drinfo)
12256+ goto out;
12257+ AuDebugOn(lkup->dirren.ninfo < bindex + 1);
12258+ drinfo = lkup->dirren.drinfo[bindex + 1];
12259+ if (!drinfo)
12260+ goto out;
12261+
12262+ match = (drinfo->ino == h_ino);
12263+ AuDbg("match %d\n", match);
12264+
12265+out:
12266+ return match;
12267+}
12268+
12269+/* ---------------------------------------------------------------------- */
12270+
12271+int au_dr_opt_set(struct super_block *sb)
12272+{
12273+ int err;
12274+ aufs_bindex_t bindex, bbot;
12275+ struct au_branch *br;
12276+
12277+ err = 0;
12278+ bbot = au_sbbot(sb);
12279+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12280+ br = au_sbr(sb, bindex);
12281+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path);
12282+ }
12283+
12284+ return err;
12285+}
12286+
12287+int au_dr_opt_flush(struct super_block *sb)
12288+{
12289+ int err;
12290+ aufs_bindex_t bindex, bbot;
12291+ struct au_branch *br;
12292+
12293+ err = 0;
12294+ bbot = au_sbbot(sb);
12295+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12296+ br = au_sbr(sb, bindex);
12297+ if (au_br_writable(br->br_perm))
12298+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL);
12299+ }
12300+
12301+ return err;
12302+}
12303+
12304+int au_dr_opt_clr(struct super_block *sb, int no_flush)
12305+{
12306+ int err;
12307+ aufs_bindex_t bindex, bbot;
12308+ struct au_branch *br;
12309+
12310+ err = 0;
12311+ if (!no_flush) {
12312+ err = au_dr_opt_flush(sb);
12313+ if (unlikely(err))
12314+ goto out;
12315+ }
12316+
12317+ bbot = au_sbbot(sb);
12318+ for (bindex = 0; bindex <= bbot; bindex++) {
12319+ br = au_sbr(sb, bindex);
12320+ au_dr_hino_free(&br->br_dirren);
12321+ }
12322+
12323+out:
12324+ return err;
12325+}
12326diff -urN /usr/share/empty/fs/aufs/dirren.h linux/fs/aufs/dirren.h
fbc438ed
JR
12327--- /usr/share/empty/fs/aufs/dirren.h 1970-01-01 08:00:00.000000000 +0800
12328+++ linux/fs/aufs/dirren.h 2019-07-11 21:21:54.379051070 +0800
062440b3
AM
12329@@ -0,0 +1,140 @@
12330+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 12331+/*
ba1aed25 12332+ * Copyright (C) 2017-2019 Junjiro R. Okajima
8b6a4947
AM
12333+ *
12334+ * This program, aufs is free software; you can redistribute it and/or modify
12335+ * it under the terms of the GNU General Public License as published by
12336+ * the Free Software Foundation; either version 2 of the License, or
12337+ * (at your option) any later version.
12338+ *
12339+ * This program is distributed in the hope that it will be useful,
12340+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12341+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12342+ * GNU General Public License for more details.
12343+ *
12344+ * You should have received a copy of the GNU General Public License
12345+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
12346+ */
12347+
12348+/*
12349+ * renamed dir info
12350+ */
12351+
12352+#ifndef __AUFS_DIRREN_H__
12353+#define __AUFS_DIRREN_H__
12354+
12355+#ifdef __KERNEL__
12356+
12357+#include <linux/dcache.h>
12358+#include <linux/statfs.h>
12359+#include <linux/uuid.h>
12360+#include "hbl.h"
12361+
12362+#define AuDirren_NHASH 100
12363+
12364+#ifdef CONFIG_AUFS_DIRREN
12365+enum au_brid_type {
12366+ AuBrid_Unset,
12367+ AuBrid_UUID,
12368+ AuBrid_FSID,
12369+ AuBrid_DEV
12370+};
12371+
12372+struct au_dr_brid {
12373+ enum au_brid_type type;
12374+ union {
12375+ uuid_t uuid; /* unimplemented yet */
12376+ fsid_t fsid;
12377+ dev_t dev;
12378+ };
12379+};
12380+
12381+/* 20 is the max digits length of ulong 64 */
12382+/* brid-type "_" uuid "_" inum */
12383+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20)
12384+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20)
12385+
12386+struct au_dr_hino {
12387+ struct hlist_bl_node dr_hnode;
12388+ ino_t dr_h_ino;
12389+};
12390+
12391+struct au_dr_br {
12392+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH];
12393+ struct au_dr_brid dr_brid;
12394+};
12395+
12396+struct au_dr_lookup {
12397+ /* dr_name is pointed by struct au_do_lookup_args.name */
12398+ struct qstr dr_name; /* subset of dr_info */
12399+ aufs_bindex_t ninfo;
12400+ struct au_drinfo **drinfo;
12401+};
12402+#else
12403+struct au_dr_hino;
12404+/* empty */
12405+struct au_dr_br { };
12406+struct au_dr_lookup { };
12407+#endif
12408+
12409+/* ---------------------------------------------------------------------- */
12410+
12411+struct au_branch;
12412+struct au_do_lookup_args;
12413+struct au_hinode;
12414+#ifdef CONFIG_AUFS_DIRREN
12415+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino,
12416+ struct au_dr_hino *add_ent);
12417+void au_dr_hino_free(struct au_dr_br *dr);
12418+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
12419+ const struct path *path);
12420+int au_dr_br_fin(struct super_block *sb, struct au_branch *br);
12421+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
12422+ struct qstr *dst_name, void *_rev);
12423+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev);
12424+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev);
12425+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12426+ aufs_bindex_t bindex);
12427+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12428+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12429+ ino_t h_ino);
12430+void au_dr_lkup_fin(struct au_do_lookup_args *lkup);
12431+int au_dr_opt_set(struct super_block *sb);
12432+int au_dr_opt_flush(struct super_block *sb);
12433+int au_dr_opt_clr(struct super_block *sb, int no_flush);
12434+#else
12435+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino,
12436+ struct au_dr_hino *add_ent);
12437+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr);
12438+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br,
12439+ const struct path *path);
12440+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br);
12441+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex,
12442+ struct qstr *dst_name, void *_rev);
12443+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev);
12444+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex,
12445+ void *rev);
12446+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry,
12447+ aufs_bindex_t bindex);
12448+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12449+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup,
12450+ aufs_bindex_t bindex, ino_t h_ino);
12451+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup);
12452+AuStubInt0(au_dr_opt_set, struct super_block *sb);
12453+AuStubInt0(au_dr_opt_flush, struct super_block *sb);
12454+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush);
12455+#endif
12456+
12457+/* ---------------------------------------------------------------------- */
12458+
12459+#ifdef CONFIG_AUFS_DIRREN
12460+static inline int au_dr_ihash(ino_t h_ino)
12461+{
12462+ return h_ino % AuDirren_NHASH;
12463+}
12464+#else
12465+AuStubInt0(au_dr_ihash, ino_t h_ino);
12466+#endif
12467+
12468+#endif /* __KERNEL__ */
12469+#endif /* __AUFS_DIRREN_H__ */
7f207e10 12470diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
fbc438ed
JR
12471--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 08:00:00.000000000 +0800
12472+++ linux/fs/aufs/dynop.c 2019-07-11 21:21:54.379051070 +0800
12473@@ -0,0 +1,367 @@
cd7a4cd9 12474+// SPDX-License-Identifier: GPL-2.0
1facf9fc 12475+/*
ba1aed25 12476+ * Copyright (C) 2010-2019 Junjiro R. Okajima
1facf9fc 12477+ *
12478+ * This program, aufs is free software; you can redistribute it and/or modify
12479+ * it under the terms of the GNU General Public License as published by
12480+ * the Free Software Foundation; either version 2 of the License, or
12481+ * (at your option) any later version.
dece6358
AM
12482+ *
12483+ * This program is distributed in the hope that it will be useful,
12484+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12485+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12486+ * GNU General Public License for more details.
12487+ *
12488+ * You should have received a copy of the GNU General Public License
523b37e3 12489+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 12490+ */
12491+
12492+/*
4a4d8108 12493+ * dynamically customizable operations for regular files
1facf9fc 12494+ */
12495+
1facf9fc 12496+#include "aufs.h"
12497+
4a4d8108 12498+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 12499+
4a4d8108
AM
12500+/*
12501+ * How large will these lists be?
12502+ * Usually just a few elements, 20-30 at most for each, I guess.
12503+ */
8b6a4947 12504+static struct hlist_bl_head dynop[AuDyLast];
4a4d8108 12505+
8b6a4947
AM
12506+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl,
12507+ const void *h_op)
1facf9fc 12508+{
4a4d8108 12509+ struct au_dykey *key, *tmp;
8b6a4947 12510+ struct hlist_bl_node *pos;
1facf9fc 12511+
4a4d8108 12512+ key = NULL;
8b6a4947
AM
12513+ hlist_bl_lock(hbl);
12514+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12515+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12516+ if (kref_get_unless_zero(&tmp->dk_kref))
12517+ key = tmp;
4a4d8108
AM
12518+ break;
12519+ }
8b6a4947 12520+ hlist_bl_unlock(hbl);
4a4d8108
AM
12521+
12522+ return key;
1facf9fc 12523+}
12524+
4a4d8108 12525+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 12526+{
4a4d8108
AM
12527+ struct au_dykey **k, *found;
12528+ const void *h_op = key->dk_op.dy_hop;
12529+ int i;
1facf9fc 12530+
4a4d8108
AM
12531+ found = NULL;
12532+ k = br->br_dykey;
12533+ for (i = 0; i < AuBrDynOp; i++)
12534+ if (k[i]) {
12535+ if (k[i]->dk_op.dy_hop == h_op) {
12536+ found = k[i];
12537+ break;
12538+ }
12539+ } else
12540+ break;
12541+ if (!found) {
12542+ spin_lock(&br->br_dykey_lock);
12543+ for (; i < AuBrDynOp; i++)
12544+ if (k[i]) {
12545+ if (k[i]->dk_op.dy_hop == h_op) {
12546+ found = k[i];
12547+ break;
12548+ }
12549+ } else {
12550+ k[i] = key;
12551+ break;
12552+ }
12553+ spin_unlock(&br->br_dykey_lock);
12554+ BUG_ON(i == AuBrDynOp); /* expand the array */
12555+ }
12556+
12557+ return found;
1facf9fc 12558+}
12559+
4a4d8108 12560+/* kref_get() if @key is already added */
8b6a4947 12561+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key)
4a4d8108
AM
12562+{
12563+ struct au_dykey *tmp, *found;
8b6a4947 12564+ struct hlist_bl_node *pos;
4a4d8108 12565+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 12566+
4a4d8108 12567+ found = NULL;
8b6a4947
AM
12568+ hlist_bl_lock(hbl);
12569+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12570+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12571+ if (kref_get_unless_zero(&tmp->dk_kref))
12572+ found = tmp;
4a4d8108
AM
12573+ break;
12574+ }
12575+ if (!found)
8b6a4947
AM
12576+ hlist_bl_add_head(&key->dk_hnode, hbl);
12577+ hlist_bl_unlock(hbl);
1facf9fc 12578+
4a4d8108
AM
12579+ if (!found)
12580+ DyPrSym(key);
12581+ return found;
12582+}
12583+
12584+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 12585+{
4a4d8108
AM
12586+ struct au_dykey *key;
12587+
12588+ key = container_of(rcu, struct au_dykey, dk_rcu);
12589+ DyPrSym(key);
83b672a5 12590+ kfree(key);
1facf9fc 12591+}
12592+
4a4d8108
AM
12593+static void dy_free(struct kref *kref)
12594+{
12595+ struct au_dykey *key;
8b6a4947 12596+ struct hlist_bl_head *hbl;
1facf9fc 12597+
4a4d8108 12598+ key = container_of(kref, struct au_dykey, dk_kref);
8b6a4947
AM
12599+ hbl = dynop + key->dk_op.dy_type;
12600+ au_hbl_del(&key->dk_hnode, hbl);
4a4d8108
AM
12601+ call_rcu(&key->dk_rcu, dy_free_rcu);
12602+}
12603+
12604+void au_dy_put(struct au_dykey *key)
1facf9fc 12605+{
4a4d8108
AM
12606+ kref_put(&key->dk_kref, dy_free);
12607+}
1facf9fc 12608+
4a4d8108
AM
12609+/* ---------------------------------------------------------------------- */
12610+
12611+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
12612+
12613+#ifdef CONFIG_AUFS_DEBUG
12614+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 12615+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
12616+#else
12617+#define DyDbgDeclare(cnt) do {} while (0)
12618+#define DyDbgInc(cnt) do {} while (0)
12619+#endif
12620+
12621+#define DySet(func, dst, src, h_op, h_sb) do { \
12622+ DyDbgInc(cnt); \
12623+ if (h_op->func) { \
12624+ if (src.func) \
12625+ dst.func = src.func; \
12626+ else \
12627+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
12628+ } \
12629+} while (0)
12630+
12631+#define DySetForce(func, dst, src) do { \
12632+ AuDebugOn(!src.func); \
12633+ DyDbgInc(cnt); \
12634+ dst.func = src.func; \
12635+} while (0)
12636+
12637+#define DySetAop(func) \
12638+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
12639+#define DySetAopForce(func) \
12640+ DySetForce(func, dyaop->da_op, aufs_aop)
12641+
12642+static void dy_aop(struct au_dykey *key, const void *h_op,
12643+ struct super_block *h_sb __maybe_unused)
12644+{
12645+ struct au_dyaop *dyaop = (void *)key;
12646+ const struct address_space_operations *h_aop = h_op;
12647+ DyDbgDeclare(cnt);
12648+
12649+ AuDbg("%s\n", au_sbtype(h_sb));
12650+
12651+ DySetAop(writepage);
12652+ DySetAopForce(readpage); /* force */
4a4d8108
AM
12653+ DySetAop(writepages);
12654+ DySetAop(set_page_dirty);
12655+ DySetAop(readpages);
12656+ DySetAop(write_begin);
12657+ DySetAop(write_end);
12658+ DySetAop(bmap);
12659+ DySetAop(invalidatepage);
12660+ DySetAop(releasepage);
027c5e7a 12661+ DySetAop(freepage);
7e9cd9fe 12662+ /* this one will be changed according to an aufs mount option */
4a4d8108 12663+ DySetAop(direct_IO);
4a4d8108 12664+ DySetAop(migratepage);
e2f27e51
AM
12665+ DySetAop(isolate_page);
12666+ DySetAop(putback_page);
4a4d8108
AM
12667+ DySetAop(launder_page);
12668+ DySetAop(is_partially_uptodate);
392086de 12669+ DySetAop(is_dirty_writeback);
4a4d8108 12670+ DySetAop(error_remove_page);
b4510431
AM
12671+ DySetAop(swap_activate);
12672+ DySetAop(swap_deactivate);
4a4d8108
AM
12673+
12674+ DyDbgSize(cnt, *h_aop);
4a4d8108
AM
12675+}
12676+
4a4d8108
AM
12677+/* ---------------------------------------------------------------------- */
12678+
12679+static void dy_bug(struct kref *kref)
12680+{
12681+ BUG();
12682+}
12683+
12684+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
12685+{
12686+ struct au_dykey *key, *old;
8b6a4947 12687+ struct hlist_bl_head *hbl;
b752ccd1 12688+ struct op {
4a4d8108 12689+ unsigned int sz;
b752ccd1
AM
12690+ void (*set)(struct au_dykey *key, const void *h_op,
12691+ struct super_block *h_sb __maybe_unused);
12692+ };
12693+ static const struct op a[] = {
4a4d8108
AM
12694+ [AuDy_AOP] = {
12695+ .sz = sizeof(struct au_dyaop),
b752ccd1 12696+ .set = dy_aop
4a4d8108 12697+ }
b752ccd1
AM
12698+ };
12699+ const struct op *p;
4a4d8108 12700+
8b6a4947
AM
12701+ hbl = dynop + op->dy_type;
12702+ key = dy_gfind_get(hbl, op->dy_hop);
4a4d8108
AM
12703+ if (key)
12704+ goto out_add; /* success */
12705+
12706+ p = a + op->dy_type;
12707+ key = kzalloc(p->sz, GFP_NOFS);
12708+ if (unlikely(!key)) {
12709+ key = ERR_PTR(-ENOMEM);
12710+ goto out;
12711+ }
12712+
12713+ key->dk_op.dy_hop = op->dy_hop;
12714+ kref_init(&key->dk_kref);
86dc4139 12715+ p->set(key, op->dy_hop, au_br_sb(br));
8b6a4947 12716+ old = dy_gadd(hbl, key);
4a4d8108 12717+ if (old) {
9f237c51 12718+ au_kfree_rcu(key);
4a4d8108
AM
12719+ key = old;
12720+ }
12721+
12722+out_add:
12723+ old = dy_bradd(br, key);
12724+ if (old)
12725+ /* its ref-count should never be zero here */
12726+ kref_put(&key->dk_kref, dy_bug);
12727+out:
12728+ return key;
12729+}
12730+
12731+/* ---------------------------------------------------------------------- */
12732+/*
acd2b654 12733+ * Aufs prohibits O_DIRECT by default even if the branch supports it.
c1595e42 12734+ * This behaviour is necessary to return an error from open(O_DIRECT) instead
4a4d8108
AM
12735+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
12736+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
12737+ * See the aufs manual in detail.
4a4d8108
AM
12738+ */
12739+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
12740+{
7e9cd9fe 12741+ if (!do_dx)
4a4d8108 12742+ dyaop->da_op.direct_IO = NULL;
7e9cd9fe 12743+ else
4a4d8108 12744+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
4a4d8108
AM
12745+}
12746+
12747+static struct au_dyaop *dy_aget(struct au_branch *br,
12748+ const struct address_space_operations *h_aop,
12749+ int do_dx)
12750+{
12751+ struct au_dyaop *dyaop;
12752+ struct au_dynop op;
12753+
12754+ op.dy_type = AuDy_AOP;
12755+ op.dy_haop = h_aop;
12756+ dyaop = (void *)dy_get(&op, br);
12757+ if (IS_ERR(dyaop))
12758+ goto out;
12759+ dy_adx(dyaop, do_dx);
12760+
12761+out:
12762+ return dyaop;
12763+}
12764+
12765+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12766+ struct inode *h_inode)
12767+{
12768+ int err, do_dx;
12769+ struct super_block *sb;
12770+ struct au_branch *br;
12771+ struct au_dyaop *dyaop;
12772+
12773+ AuDebugOn(!S_ISREG(h_inode->i_mode));
12774+ IiMustWriteLock(inode);
12775+
12776+ sb = inode->i_sb;
12777+ br = au_sbr(sb, bindex);
12778+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
12779+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
12780+ err = PTR_ERR(dyaop);
12781+ if (IS_ERR(dyaop))
12782+ /* unnecessary to call dy_fput() */
12783+ goto out;
12784+
12785+ err = 0;
12786+ inode->i_mapping->a_ops = &dyaop->da_op;
12787+
12788+out:
12789+ return err;
12790+}
12791+
b752ccd1
AM
12792+/*
12793+ * Is it safe to replace a_ops during the inode/file is in operation?
12794+ * Yes, I hope so.
12795+ */
12796+int au_dy_irefresh(struct inode *inode)
12797+{
12798+ int err;
5afbbe0d 12799+ aufs_bindex_t btop;
b752ccd1
AM
12800+ struct inode *h_inode;
12801+
12802+ err = 0;
12803+ if (S_ISREG(inode->i_mode)) {
5afbbe0d
AM
12804+ btop = au_ibtop(inode);
12805+ h_inode = au_h_iptr(inode, btop);
12806+ err = au_dy_iaop(inode, btop, h_inode);
b752ccd1
AM
12807+ }
12808+ return err;
12809+}
12810+
4a4d8108
AM
12811+void au_dy_arefresh(int do_dx)
12812+{
8b6a4947
AM
12813+ struct hlist_bl_head *hbl;
12814+ struct hlist_bl_node *pos;
4a4d8108
AM
12815+ struct au_dykey *key;
12816+
8b6a4947
AM
12817+ hbl = dynop + AuDy_AOP;
12818+ hlist_bl_lock(hbl);
12819+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode)
4a4d8108 12820+ dy_adx((void *)key, do_dx);
8b6a4947 12821+ hlist_bl_unlock(hbl);
4a4d8108
AM
12822+}
12823+
4a4d8108
AM
12824+/* ---------------------------------------------------------------------- */
12825+
12826+void __init au_dy_init(void)
12827+{
12828+ int i;
12829+
4a4d8108 12830+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12831+ INIT_HLIST_BL_HEAD(dynop + i);
4a4d8108
AM
12832+}
12833+
12834+void au_dy_fin(void)
12835+{
12836+ int i;
12837+
12838+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12839+ WARN_ON(!hlist_bl_empty(dynop + i));
4a4d8108 12840+}
7f207e10 12841diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
fbc438ed
JR
12842--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 08:00:00.000000000 +0800
12843+++ linux/fs/aufs/dynop.h 2019-07-11 21:21:54.379051070 +0800
12844@@ -0,0 +1,77 @@
062440b3 12845+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 12846+/*
ba1aed25 12847+ * Copyright (C) 2010-2019 Junjiro R. Okajima
4a4d8108
AM
12848+ *
12849+ * This program, aufs is free software; you can redistribute it and/or modify
12850+ * it under the terms of the GNU General Public License as published by
12851+ * the Free Software Foundation; either version 2 of the License, or
12852+ * (at your option) any later version.
12853+ *
12854+ * This program is distributed in the hope that it will be useful,
12855+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12856+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12857+ * GNU General Public License for more details.
12858+ *
12859+ * You should have received a copy of the GNU General Public License
523b37e3 12860+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12861+ */
12862+
12863+/*
12864+ * dynamically customizable operations (for regular files only)
12865+ */
12866+
12867+#ifndef __AUFS_DYNOP_H__
12868+#define __AUFS_DYNOP_H__
12869+
12870+#ifdef __KERNEL__
12871+
7e9cd9fe
AM
12872+#include <linux/fs.h>
12873+#include <linux/kref.h>
4a4d8108 12874+
2cbb1c4b 12875+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
12876+
12877+struct au_dynop {
12878+ int dy_type;
12879+ union {
12880+ const void *dy_hop;
12881+ const struct address_space_operations *dy_haop;
4a4d8108
AM
12882+ };
12883+};
12884+
12885+struct au_dykey {
12886+ union {
8b6a4947 12887+ struct hlist_bl_node dk_hnode;
4a4d8108
AM
12888+ struct rcu_head dk_rcu;
12889+ };
12890+ struct au_dynop dk_op;
12891+
12892+ /*
12893+ * during I am in the branch local array, kref is gotten. when the
12894+ * branch is removed, kref is put.
12895+ */
12896+ struct kref dk_kref;
12897+};
12898+
12899+/* stop unioning since their sizes are very different from each other */
12900+struct au_dyaop {
12901+ struct au_dykey da_key;
12902+ struct address_space_operations da_op; /* not const */
4a4d8108 12903+};
fbc438ed
JR
12904+/* make sure that 'struct au_dykey *' can be any type */
12905+static_assert(!offsetof(struct au_dyaop, da_key));
4a4d8108 12906+
4a4d8108
AM
12907+/* ---------------------------------------------------------------------- */
12908+
12909+/* dynop.c */
12910+struct au_branch;
12911+void au_dy_put(struct au_dykey *key);
12912+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12913+ struct inode *h_inode);
b752ccd1 12914+int au_dy_irefresh(struct inode *inode);
4a4d8108 12915+void au_dy_arefresh(int do_dio);
4a4d8108
AM
12916+
12917+void __init au_dy_init(void);
12918+void au_dy_fin(void);
12919+
4a4d8108
AM
12920+#endif /* __KERNEL__ */
12921+#endif /* __AUFS_DYNOP_H__ */
7f207e10 12922diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
fbc438ed
JR
12923--- /usr/share/empty/fs/aufs/export.c 1970-01-01 08:00:00.000000000 +0800
12924+++ linux/fs/aufs/export.c 2019-07-11 21:21:54.379051070 +0800
062440b3 12925@@ -0,0 +1,838 @@
cd7a4cd9 12926+// SPDX-License-Identifier: GPL-2.0
4a4d8108 12927+/*
ba1aed25 12928+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
12929+ *
12930+ * This program, aufs is free software; you can redistribute it and/or modify
12931+ * it under the terms of the GNU General Public License as published by
12932+ * the Free Software Foundation; either version 2 of the License, or
12933+ * (at your option) any later version.
12934+ *
12935+ * This program is distributed in the hope that it will be useful,
12936+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12937+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12938+ * GNU General Public License for more details.
12939+ *
12940+ * You should have received a copy of the GNU General Public License
523b37e3 12941+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12942+ */
12943+
12944+/*
12945+ * export via nfs
12946+ */
12947+
12948+#include <linux/exportfs.h>
7eafdf33 12949+#include <linux/fs_struct.h>
4a4d8108
AM
12950+#include <linux/namei.h>
12951+#include <linux/nsproxy.h>
12952+#include <linux/random.h>
12953+#include <linux/writeback.h>
12954+#include "aufs.h"
12955+
12956+union conv {
12957+#ifdef CONFIG_AUFS_INO_T_64
12958+ __u32 a[2];
12959+#else
12960+ __u32 a[1];
12961+#endif
12962+ ino_t ino;
12963+};
12964+
12965+static ino_t decode_ino(__u32 *a)
12966+{
12967+ union conv u;
12968+
12969+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
12970+ u.a[0] = a[0];
12971+#ifdef CONFIG_AUFS_INO_T_64
12972+ u.a[1] = a[1];
12973+#endif
12974+ return u.ino;
12975+}
12976+
12977+static void encode_ino(__u32 *a, ino_t ino)
12978+{
12979+ union conv u;
12980+
12981+ u.ino = ino;
12982+ a[0] = u.a[0];
12983+#ifdef CONFIG_AUFS_INO_T_64
12984+ a[1] = u.a[1];
12985+#endif
12986+}
12987+
12988+/* NFS file handle */
12989+enum {
12990+ Fh_br_id,
12991+ Fh_sigen,
12992+#ifdef CONFIG_AUFS_INO_T_64
12993+ /* support 64bit inode number */
12994+ Fh_ino1,
12995+ Fh_ino2,
12996+ Fh_dir_ino1,
12997+ Fh_dir_ino2,
12998+#else
12999+ Fh_ino1,
13000+ Fh_dir_ino1,
13001+#endif
13002+ Fh_igen,
13003+ Fh_h_type,
13004+ Fh_tail,
13005+
13006+ Fh_ino = Fh_ino1,
13007+ Fh_dir_ino = Fh_dir_ino1
13008+};
13009+
13010+static int au_test_anon(struct dentry *dentry)
13011+{
027c5e7a 13012+ /* note: read d_flags without d_lock */
4a4d8108
AM
13013+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
13014+}
13015+
a2a7ad62
AM
13016+int au_test_nfsd(void)
13017+{
13018+ int ret;
13019+ struct task_struct *tsk = current;
13020+ char comm[sizeof(tsk->comm)];
13021+
13022+ ret = 0;
13023+ if (tsk->flags & PF_KTHREAD) {
13024+ get_task_comm(comm, tsk);
13025+ ret = !strcmp(comm, "nfsd");
13026+ }
13027+
13028+ return ret;
13029+}
13030+
4a4d8108
AM
13031+/* ---------------------------------------------------------------------- */
13032+/* inode generation external table */
13033+
b752ccd1 13034+void au_xigen_inc(struct inode *inode)
4a4d8108 13035+{
4a4d8108
AM
13036+ loff_t pos;
13037+ ssize_t sz;
13038+ __u32 igen;
13039+ struct super_block *sb;
13040+ struct au_sbinfo *sbinfo;
13041+
4a4d8108 13042+ sb = inode->i_sb;
b752ccd1 13043+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 13044+
b752ccd1 13045+ sbinfo = au_sbi(sb);
1facf9fc 13046+ pos = inode->i_ino;
13047+ pos *= sizeof(igen);
13048+ igen = inode->i_generation + 1;
1facf9fc 13049+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
13050+ sizeof(igen), &pos);
13051+ if (sz == sizeof(igen))
b752ccd1 13052+ return; /* success */
1facf9fc 13053+
b752ccd1 13054+ if (unlikely(sz >= 0))
1facf9fc 13055+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 13056+}
13057+
13058+int au_xigen_new(struct inode *inode)
13059+{
13060+ int err;
13061+ loff_t pos;
13062+ ssize_t sz;
13063+ struct super_block *sb;
13064+ struct au_sbinfo *sbinfo;
13065+ struct file *file;
13066+
13067+ err = 0;
13068+ /* todo: dirty, at mount time */
13069+ if (inode->i_ino == AUFS_ROOT_INO)
13070+ goto out;
13071+ sb = inode->i_sb;
dece6358 13072+ SiMustAnyLock(sb);
1facf9fc 13073+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
13074+ goto out;
13075+
13076+ err = -EFBIG;
13077+ pos = inode->i_ino;
13078+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
13079+ AuIOErr1("too large i%lld\n", pos);
13080+ goto out;
13081+ }
13082+ pos *= sizeof(inode->i_generation);
13083+
13084+ err = 0;
13085+ sbinfo = au_sbi(sb);
13086+ file = sbinfo->si_xigen;
13087+ BUG_ON(!file);
13088+
c06a8ce3 13089+ if (vfsub_f_size_read(file)
1facf9fc 13090+ < pos + sizeof(inode->i_generation)) {
13091+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
13092+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
13093+ sizeof(inode->i_generation), &pos);
13094+ } else
13095+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
13096+ sizeof(inode->i_generation), &pos);
13097+ if (sz == sizeof(inode->i_generation))
13098+ goto out; /* success */
13099+
13100+ err = sz;
13101+ if (unlikely(sz >= 0)) {
13102+ err = -EIO;
13103+ AuIOErr("xigen error (%zd)\n", sz);
13104+ }
13105+
4f0767ce 13106+out:
1facf9fc 13107+ return err;
13108+}
13109+
062440b3 13110+int au_xigen_set(struct super_block *sb, struct path *path)
1facf9fc 13111+{
13112+ int err;
13113+ struct au_sbinfo *sbinfo;
13114+ struct file *file;
13115+
dece6358
AM
13116+ SiMustWriteLock(sb);
13117+
1facf9fc 13118+ sbinfo = au_sbi(sb);
062440b3 13119+ file = au_xino_create2(sb, path, sbinfo->si_xigen);
1facf9fc 13120+ err = PTR_ERR(file);
13121+ if (IS_ERR(file))
13122+ goto out;
13123+ err = 0;
13124+ if (sbinfo->si_xigen)
13125+ fput(sbinfo->si_xigen);
13126+ sbinfo->si_xigen = file;
13127+
4f0767ce 13128+out:
062440b3 13129+ AuTraceErr(err);
1facf9fc 13130+ return err;
13131+}
13132+
13133+void au_xigen_clr(struct super_block *sb)
13134+{
13135+ struct au_sbinfo *sbinfo;
13136+
dece6358
AM
13137+ SiMustWriteLock(sb);
13138+
1facf9fc 13139+ sbinfo = au_sbi(sb);
13140+ if (sbinfo->si_xigen) {
13141+ fput(sbinfo->si_xigen);
13142+ sbinfo->si_xigen = NULL;
13143+ }
13144+}
13145+
13146+/* ---------------------------------------------------------------------- */
13147+
13148+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
13149+ ino_t dir_ino)
13150+{
13151+ struct dentry *dentry, *d;
13152+ struct inode *inode;
13153+ unsigned int sigen;
13154+
13155+ dentry = NULL;
13156+ inode = ilookup(sb, ino);
13157+ if (!inode)
13158+ goto out;
13159+
13160+ dentry = ERR_PTR(-ESTALE);
13161+ sigen = au_sigen(sb);
5afbbe0d 13162+ if (unlikely(au_is_bad_inode(inode)
1facf9fc 13163+ || IS_DEADDIR(inode)
537831f9 13164+ || sigen != au_iigen(inode, NULL)))
1facf9fc 13165+ goto out_iput;
13166+
13167+ dentry = NULL;
13168+ if (!dir_ino || S_ISDIR(inode->i_mode))
13169+ dentry = d_find_alias(inode);
13170+ else {
027c5e7a 13171+ spin_lock(&inode->i_lock);
c1595e42 13172+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 13173+ spin_lock(&d->d_lock);
1facf9fc 13174+ if (!au_test_anon(d)
5527c038 13175+ && d_inode(d->d_parent)->i_ino == dir_ino) {
027c5e7a
AM
13176+ dentry = dget_dlock(d);
13177+ spin_unlock(&d->d_lock);
1facf9fc 13178+ break;
13179+ }
027c5e7a
AM
13180+ spin_unlock(&d->d_lock);
13181+ }
13182+ spin_unlock(&inode->i_lock);
1facf9fc 13183+ }
027c5e7a 13184+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 13185+ /* need to refresh */
1facf9fc 13186+ dput(dentry);
2cbb1c4b 13187+ dentry = NULL;
1facf9fc 13188+ }
13189+
4f0767ce 13190+out_iput:
1facf9fc 13191+ iput(inode);
4f0767ce 13192+out:
2cbb1c4b 13193+ AuTraceErrPtr(dentry);
1facf9fc 13194+ return dentry;
13195+}
13196+
13197+/* ---------------------------------------------------------------------- */
13198+
13199+/* todo: dirty? */
13200+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
13201+
13202+struct au_compare_mnt_args {
13203+ /* input */
13204+ struct super_block *sb;
13205+
13206+ /* output */
13207+ struct vfsmount *mnt;
13208+};
13209+
13210+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
13211+{
13212+ struct au_compare_mnt_args *a = arg;
13213+
13214+ if (mnt->mnt_sb != a->sb)
13215+ return 0;
13216+ a->mnt = mntget(mnt);
13217+ return 1;
13218+}
13219+
1facf9fc 13220+static struct vfsmount *au_mnt_get(struct super_block *sb)
13221+{
4a4d8108 13222+ int err;
7eafdf33 13223+ struct path root;
4a4d8108
AM
13224+ struct au_compare_mnt_args args = {
13225+ .sb = sb
13226+ };
1facf9fc 13227+
7eafdf33 13228+ get_fs_root(current->fs, &root);
523b37e3 13229+ rcu_read_lock();
7eafdf33 13230+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
523b37e3 13231+ rcu_read_unlock();
7eafdf33 13232+ path_put(&root);
4a4d8108
AM
13233+ AuDebugOn(!err);
13234+ AuDebugOn(!args.mnt);
13235+ return args.mnt;
1facf9fc 13236+}
13237+
13238+struct au_nfsd_si_lock {
4a4d8108 13239+ unsigned int sigen;
027c5e7a 13240+ aufs_bindex_t bindex, br_id;
1facf9fc 13241+ unsigned char force_lock;
13242+};
13243+
027c5e7a
AM
13244+static int si_nfsd_read_lock(struct super_block *sb,
13245+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13246+{
027c5e7a 13247+ int err;
1facf9fc 13248+ aufs_bindex_t bindex;
13249+
13250+ si_read_lock(sb, AuLock_FLUSH);
13251+
13252+ /* branch id may be wrapped around */
027c5e7a 13253+ err = 0;
1facf9fc 13254+ bindex = au_br_index(sb, nsi_lock->br_id);
13255+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
13256+ goto out; /* success */
13257+
027c5e7a
AM
13258+ err = -ESTALE;
13259+ bindex = -1;
1facf9fc 13260+ if (!nsi_lock->force_lock)
13261+ si_read_unlock(sb);
1facf9fc 13262+
4f0767ce 13263+out:
027c5e7a
AM
13264+ nsi_lock->bindex = bindex;
13265+ return err;
1facf9fc 13266+}
13267+
13268+struct find_name_by_ino {
392086de 13269+ struct dir_context ctx;
1facf9fc 13270+ int called, found;
13271+ ino_t ino;
13272+ char *name;
13273+ int namelen;
13274+};
13275+
13276+static int
392086de
AM
13277+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen,
13278+ loff_t offset, u64 ino, unsigned int d_type)
1facf9fc 13279+{
392086de
AM
13280+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino,
13281+ ctx);
1facf9fc 13282+
13283+ a->called++;
13284+ if (a->ino != ino)
13285+ return 0;
13286+
13287+ memcpy(a->name, name, namelen);
13288+ a->namelen = namelen;
13289+ a->found = 1;
13290+ return 1;
13291+}
13292+
13293+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
13294+ struct au_nfsd_si_lock *nsi_lock)
13295+{
13296+ struct dentry *dentry, *parent;
13297+ struct file *file;
13298+ struct inode *dir;
392086de
AM
13299+ struct find_name_by_ino arg = {
13300+ .ctx = {
2000de60 13301+ .actor = find_name_by_ino
392086de
AM
13302+ }
13303+ };
1facf9fc 13304+ int err;
13305+
13306+ parent = path->dentry;
13307+ if (nsi_lock)
13308+ si_read_unlock(parent->d_sb);
4a4d8108 13309+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 13310+ dentry = (void *)file;
13311+ if (IS_ERR(file))
13312+ goto out;
13313+
13314+ dentry = ERR_PTR(-ENOMEM);
537831f9 13315+ arg.name = (void *)__get_free_page(GFP_NOFS);
1facf9fc 13316+ if (unlikely(!arg.name))
13317+ goto out_file;
13318+ arg.ino = ino;
13319+ arg.found = 0;
13320+ do {
13321+ arg.called = 0;
13322+ /* smp_mb(); */
392086de 13323+ err = vfsub_iterate_dir(file, &arg.ctx);
1facf9fc 13324+ } while (!err && !arg.found && arg.called);
13325+ dentry = ERR_PTR(err);
13326+ if (unlikely(err))
13327+ goto out_name;
1716fcea
AM
13328+ /* instead of ENOENT */
13329+ dentry = ERR_PTR(-ESTALE);
1facf9fc 13330+ if (!arg.found)
13331+ goto out_name;
13332+
b4510431 13333+ /* do not call vfsub_lkup_one() */
5527c038 13334+ dir = d_inode(parent);
febd17d6 13335+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen);
1facf9fc 13336+ AuTraceErrPtr(dentry);
13337+ if (IS_ERR(dentry))
13338+ goto out_name;
13339+ AuDebugOn(au_test_anon(dentry));
5527c038 13340+ if (unlikely(d_really_is_negative(dentry))) {
1facf9fc 13341+ dput(dentry);
13342+ dentry = ERR_PTR(-ENOENT);
13343+ }
13344+
4f0767ce 13345+out_name:
1c60b727 13346+ free_page((unsigned long)arg.name);
4f0767ce 13347+out_file:
1facf9fc 13348+ fput(file);
4f0767ce 13349+out:
1facf9fc 13350+ if (unlikely(nsi_lock
13351+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
13352+ if (!IS_ERR(dentry)) {
13353+ dput(dentry);
13354+ dentry = ERR_PTR(-ESTALE);
13355+ }
13356+ AuTraceErrPtr(dentry);
13357+ return dentry;
13358+}
13359+
13360+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
13361+ ino_t dir_ino,
13362+ struct au_nfsd_si_lock *nsi_lock)
13363+{
13364+ struct dentry *dentry;
13365+ struct path path;
13366+
13367+ if (dir_ino != AUFS_ROOT_INO) {
13368+ path.dentry = decode_by_ino(sb, dir_ino, 0);
13369+ dentry = path.dentry;
13370+ if (!path.dentry || IS_ERR(path.dentry))
13371+ goto out;
13372+ AuDebugOn(au_test_anon(path.dentry));
13373+ } else
13374+ path.dentry = dget(sb->s_root);
13375+
13376+ path.mnt = au_mnt_get(sb);
13377+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
13378+ path_put(&path);
13379+
4f0767ce 13380+out:
1facf9fc 13381+ AuTraceErrPtr(dentry);
13382+ return dentry;
13383+}
13384+
13385+/* ---------------------------------------------------------------------- */
13386+
13387+static int h_acceptable(void *expv, struct dentry *dentry)
13388+{
13389+ return 1;
13390+}
13391+
13392+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
13393+ char *buf, int len, struct super_block *sb)
13394+{
13395+ char *p;
13396+ int n;
13397+ struct path path;
13398+
13399+ p = d_path(h_rootpath, buf, len);
13400+ if (IS_ERR(p))
13401+ goto out;
13402+ n = strlen(p);
13403+
13404+ path.mnt = h_rootpath->mnt;
13405+ path.dentry = h_parent;
13406+ p = d_path(&path, buf, len);
13407+ if (IS_ERR(p))
13408+ goto out;
13409+ if (n != 1)
13410+ p += n;
13411+
13412+ path.mnt = au_mnt_get(sb);
13413+ path.dentry = sb->s_root;
13414+ p = d_path(&path, buf, len - strlen(p));
13415+ mntput(path.mnt);
13416+ if (IS_ERR(p))
13417+ goto out;
13418+ if (n != 1)
13419+ p[strlen(p)] = '/';
13420+
4f0767ce 13421+out:
1facf9fc 13422+ AuTraceErrPtr(p);
13423+ return p;
13424+}
13425+
13426+static
027c5e7a
AM
13427+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
13428+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13429+{
13430+ struct dentry *dentry, *h_parent, *root;
13431+ struct super_block *h_sb;
13432+ char *pathname, *p;
13433+ struct vfsmount *h_mnt;
13434+ struct au_branch *br;
13435+ int err;
13436+ struct path path;
13437+
027c5e7a 13438+ br = au_sbr(sb, nsi_lock->bindex);
86dc4139 13439+ h_mnt = au_br_mnt(br);
1facf9fc 13440+ h_sb = h_mnt->mnt_sb;
13441+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
5afbbe0d 13442+ lockdep_off();
1facf9fc 13443+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
13444+ fh_len - Fh_tail, fh[Fh_h_type],
13445+ h_acceptable, /*context*/NULL);
5afbbe0d 13446+ lockdep_on();
1facf9fc 13447+ dentry = h_parent;
13448+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
13449+ AuWarn1("%s decode_fh failed, %ld\n",
13450+ au_sbtype(h_sb), PTR_ERR(h_parent));
13451+ goto out;
13452+ }
13453+ dentry = NULL;
13454+ if (unlikely(au_test_anon(h_parent))) {
13455+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
13456+ au_sbtype(h_sb));
13457+ goto out_h_parent;
13458+ }
13459+
13460+ dentry = ERR_PTR(-ENOMEM);
13461+ pathname = (void *)__get_free_page(GFP_NOFS);
13462+ if (unlikely(!pathname))
13463+ goto out_h_parent;
13464+
13465+ root = sb->s_root;
13466+ path.mnt = h_mnt;
13467+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 13468+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 13469+ di_read_unlock(root, !AuLock_IR);
13470+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
13471+ dentry = (void *)p;
13472+ if (IS_ERR(p))
13473+ goto out_pathname;
13474+
13475+ si_read_unlock(sb);
13476+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
13477+ dentry = ERR_PTR(err);
13478+ if (unlikely(err))
13479+ goto out_relock;
13480+
13481+ dentry = ERR_PTR(-ENOENT);
13482+ AuDebugOn(au_test_anon(path.dentry));
5527c038 13483+ if (unlikely(d_really_is_negative(path.dentry)))
1facf9fc 13484+ goto out_path;
13485+
5527c038 13486+ if (ino != d_inode(path.dentry)->i_ino)
1facf9fc 13487+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
13488+ else
13489+ dentry = dget(path.dentry);
13490+
4f0767ce 13491+out_path:
1facf9fc 13492+ path_put(&path);
4f0767ce 13493+out_relock:
1facf9fc 13494+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
13495+ if (!IS_ERR(dentry)) {
13496+ dput(dentry);
13497+ dentry = ERR_PTR(-ESTALE);
13498+ }
4f0767ce 13499+out_pathname:
1c60b727 13500+ free_page((unsigned long)pathname);
4f0767ce 13501+out_h_parent:
1facf9fc 13502+ dput(h_parent);
4f0767ce 13503+out:
1facf9fc 13504+ AuTraceErrPtr(dentry);
13505+ return dentry;
13506+}
13507+
13508+/* ---------------------------------------------------------------------- */
13509+
13510+static struct dentry *
13511+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
13512+ int fh_type)
13513+{
13514+ struct dentry *dentry;
13515+ __u32 *fh = fid->raw;
027c5e7a 13516+ struct au_branch *br;
1facf9fc 13517+ ino_t ino, dir_ino;
1facf9fc 13518+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 13519+ .force_lock = 0
13520+ };
13521+
1facf9fc 13522+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
13523+ /* it should never happen, but the file handle is unreliable */
13524+ if (unlikely(fh_len < Fh_tail))
13525+ goto out;
13526+ nsi_lock.sigen = fh[Fh_sigen];
13527+ nsi_lock.br_id = fh[Fh_br_id];
13528+
1facf9fc 13529+ /* branch id may be wrapped around */
027c5e7a
AM
13530+ br = NULL;
13531+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 13532+ goto out;
13533+ nsi_lock.force_lock = 1;
13534+
13535+ /* is this inode still cached? */
13536+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
13537+ /* it should never happen */
13538+ if (unlikely(ino == AUFS_ROOT_INO))
8cdd5066 13539+ goto out_unlock;
4a4d8108 13540+
1facf9fc 13541+ dir_ino = decode_ino(fh + Fh_dir_ino);
13542+ dentry = decode_by_ino(sb, ino, dir_ino);
13543+ if (IS_ERR(dentry))
13544+ goto out_unlock;
13545+ if (dentry)
13546+ goto accept;
13547+
13548+ /* is the parent dir cached? */
027c5e7a 13549+ br = au_sbr(sb, nsi_lock.bindex);
acd2b654 13550+ au_lcnt_inc(&br->br_nfiles);
1facf9fc 13551+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
13552+ if (IS_ERR(dentry))
13553+ goto out_unlock;
13554+ if (dentry)
13555+ goto accept;
13556+
13557+ /* lookup path */
027c5e7a 13558+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 13559+ if (IS_ERR(dentry))
13560+ goto out_unlock;
13561+ if (unlikely(!dentry))
13562+ /* todo?: make it ESTALE */
13563+ goto out_unlock;
13564+
4f0767ce 13565+accept:
027c5e7a 13566+ if (!au_digen_test(dentry, au_sigen(sb))
5527c038 13567+ && d_inode(dentry)->i_generation == fh[Fh_igen])
1facf9fc 13568+ goto out_unlock; /* success */
13569+
13570+ dput(dentry);
13571+ dentry = ERR_PTR(-ESTALE);
4f0767ce 13572+out_unlock:
027c5e7a 13573+ if (br)
acd2b654 13574+ au_lcnt_dec(&br->br_nfiles);
1facf9fc 13575+ si_read_unlock(sb);
4f0767ce 13576+out:
1facf9fc 13577+ AuTraceErrPtr(dentry);
13578+ return dentry;
13579+}
13580+
13581+#if 0 /* reserved for future use */
13582+/* support subtreecheck option */
13583+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
13584+ int fh_len, int fh_type)
13585+{
13586+ struct dentry *parent;
13587+ __u32 *fh = fid->raw;
13588+ ino_t dir_ino;
13589+
13590+ dir_ino = decode_ino(fh + Fh_dir_ino);
13591+ parent = decode_by_ino(sb, dir_ino, 0);
13592+ if (IS_ERR(parent))
13593+ goto out;
13594+ if (!parent)
13595+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
13596+ dir_ino, fh, fh_len);
13597+
4f0767ce 13598+out:
1facf9fc 13599+ AuTraceErrPtr(parent);
13600+ return parent;
13601+}
13602+#endif
13603+
13604+/* ---------------------------------------------------------------------- */
13605+
0c3ec466
AM
13606+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
13607+ struct inode *dir)
1facf9fc 13608+{
13609+ int err;
0c3ec466 13610+ aufs_bindex_t bindex;
1facf9fc 13611+ struct super_block *sb, *h_sb;
0c3ec466
AM
13612+ struct dentry *dentry, *parent, *h_parent;
13613+ struct inode *h_dir;
1facf9fc 13614+ struct au_branch *br;
13615+
1facf9fc 13616+ err = -ENOSPC;
13617+ if (unlikely(*max_len <= Fh_tail)) {
13618+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
13619+ goto out;
13620+ }
13621+
13622+ err = FILEID_ROOT;
0c3ec466
AM
13623+ if (inode->i_ino == AUFS_ROOT_INO) {
13624+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
1facf9fc 13625+ goto out;
13626+ }
13627+
1facf9fc 13628+ h_parent = NULL;
0c3ec466
AM
13629+ sb = inode->i_sb;
13630+ err = si_read_lock(sb, AuLock_FLUSH);
027c5e7a
AM
13631+ if (unlikely(err))
13632+ goto out;
13633+
1facf9fc 13634+#ifdef CONFIG_AUFS_DEBUG
13635+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
13636+ AuWarn1("NFS-exporting requires xino\n");
13637+#endif
027c5e7a 13638+ err = -EIO;
0c3ec466
AM
13639+ parent = NULL;
13640+ ii_read_lock_child(inode);
5afbbe0d 13641+ bindex = au_ibtop(inode);
0c3ec466 13642+ if (!dir) {
c1595e42 13643+ dentry = d_find_any_alias(inode);
0c3ec466
AM
13644+ if (unlikely(!dentry))
13645+ goto out_unlock;
13646+ AuDebugOn(au_test_anon(dentry));
13647+ parent = dget_parent(dentry);
13648+ dput(dentry);
13649+ if (unlikely(!parent))
13650+ goto out_unlock;
5527c038
JR
13651+ if (d_really_is_positive(parent))
13652+ dir = d_inode(parent);
1facf9fc 13653+ }
0c3ec466
AM
13654+
13655+ ii_read_lock_parent(dir);
13656+ h_dir = au_h_iptr(dir, bindex);
13657+ ii_read_unlock(dir);
13658+ if (unlikely(!h_dir))
13659+ goto out_parent;
c1595e42 13660+ h_parent = d_find_any_alias(h_dir);
1facf9fc 13661+ if (unlikely(!h_parent))
0c3ec466 13662+ goto out_hparent;
1facf9fc 13663+
13664+ err = -EPERM;
13665+ br = au_sbr(sb, bindex);
86dc4139 13666+ h_sb = au_br_sb(br);
1facf9fc 13667+ if (unlikely(!h_sb->s_export_op)) {
13668+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
0c3ec466 13669+ goto out_hparent;
1facf9fc 13670+ }
13671+
13672+ fh[Fh_br_id] = br->br_id;
13673+ fh[Fh_sigen] = au_sigen(sb);
13674+ encode_ino(fh + Fh_ino, inode->i_ino);
0c3ec466 13675+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
1facf9fc 13676+ fh[Fh_igen] = inode->i_generation;
13677+
13678+ *max_len -= Fh_tail;
13679+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
13680+ max_len,
13681+ /*connectable or subtreecheck*/0);
13682+ err = fh[Fh_h_type];
13683+ *max_len += Fh_tail;
13684+ /* todo: macros? */
1716fcea 13685+ if (err != FILEID_INVALID)
1facf9fc 13686+ err = 99;
13687+ else
13688+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
13689+
0c3ec466 13690+out_hparent:
1facf9fc 13691+ dput(h_parent);
0c3ec466 13692+out_parent:
1facf9fc 13693+ dput(parent);
0c3ec466
AM
13694+out_unlock:
13695+ ii_read_unlock(inode);
13696+ si_read_unlock(sb);
4f0767ce 13697+out:
1facf9fc 13698+ if (unlikely(err < 0))
1716fcea 13699+ err = FILEID_INVALID;
1facf9fc 13700+ return err;
13701+}
13702+
13703+/* ---------------------------------------------------------------------- */
13704+
4a4d8108
AM
13705+static int aufs_commit_metadata(struct inode *inode)
13706+{
13707+ int err;
13708+ aufs_bindex_t bindex;
13709+ struct super_block *sb;
13710+ struct inode *h_inode;
13711+ int (*f)(struct inode *inode);
13712+
13713+ sb = inode->i_sb;
e49829fe 13714+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 13715+ ii_write_lock_child(inode);
5afbbe0d 13716+ bindex = au_ibtop(inode);
4a4d8108
AM
13717+ AuDebugOn(bindex < 0);
13718+ h_inode = au_h_iptr(inode, bindex);
13719+
13720+ f = h_inode->i_sb->s_export_op->commit_metadata;
13721+ if (f)
13722+ err = f(h_inode);
13723+ else {
13724+ struct writeback_control wbc = {
13725+ .sync_mode = WB_SYNC_ALL,
13726+ .nr_to_write = 0 /* metadata only */
13727+ };
13728+
13729+ err = sync_inode(h_inode, &wbc);
13730+ }
13731+
13732+ au_cpup_attr_timesizes(inode);
13733+ ii_write_unlock(inode);
13734+ si_read_unlock(sb);
13735+ return err;
13736+}
13737+
13738+/* ---------------------------------------------------------------------- */
13739+
1facf9fc 13740+static struct export_operations aufs_export_op = {
4a4d8108 13741+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 13742+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
13743+ .encode_fh = aufs_encode_fh,
13744+ .commit_metadata = aufs_commit_metadata
1facf9fc 13745+};
13746+
13747+void au_export_init(struct super_block *sb)
13748+{
13749+ struct au_sbinfo *sbinfo;
13750+ __u32 u;
13751+
5afbbe0d
AM
13752+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS)
13753+ && IS_MODULE(CONFIG_EXPORTFS),
13754+ AUFS_NAME ": unsupported configuration "
13755+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y");
13756+
1facf9fc 13757+ sb->s_export_op = &aufs_export_op;
13758+ sbinfo = au_sbi(sb);
13759+ sbinfo->si_xigen = NULL;
13760+ get_random_bytes(&u, sizeof(u));
13761+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
13762+ atomic_set(&sbinfo->si_xigen_next, u);
13763+}
076b876e 13764diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
fbc438ed
JR
13765--- /usr/share/empty/fs/aufs/fhsm.c 1970-01-01 08:00:00.000000000 +0800
13766+++ linux/fs/aufs/fhsm.c 2019-07-11 21:21:54.379051070 +0800
062440b3 13767@@ -0,0 +1,427 @@
cd7a4cd9 13768+// SPDX-License-Identifier: GPL-2.0
076b876e 13769+/*
ba1aed25 13770+ * Copyright (C) 2011-2019 Junjiro R. Okajima
076b876e
AM
13771+ *
13772+ * This program, aufs is free software; you can redistribute it and/or modify
13773+ * it under the terms of the GNU General Public License as published by
13774+ * the Free Software Foundation; either version 2 of the License, or
13775+ * (at your option) any later version.
13776+ *
13777+ * This program is distributed in the hope that it will be useful,
13778+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13779+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13780+ * GNU General Public License for more details.
13781+ *
13782+ * You should have received a copy of the GNU General Public License
13783+ * along with this program; if not, write to the Free Software
13784+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13785+ */
13786+
13787+/*
13788+ * File-based Hierarchy Storage Management
13789+ */
13790+
13791+#include <linux/anon_inodes.h>
13792+#include <linux/poll.h>
13793+#include <linux/seq_file.h>
13794+#include <linux/statfs.h>
13795+#include "aufs.h"
13796+
c1595e42
JR
13797+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb)
13798+{
13799+ struct au_sbinfo *sbinfo;
13800+ struct au_fhsm *fhsm;
13801+
13802+ SiMustAnyLock(sb);
13803+
13804+ sbinfo = au_sbi(sb);
13805+ fhsm = &sbinfo->si_fhsm;
13806+ AuDebugOn(!fhsm);
13807+ return fhsm->fhsm_bottom;
13808+}
13809+
13810+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex)
13811+{
13812+ struct au_sbinfo *sbinfo;
13813+ struct au_fhsm *fhsm;
13814+
13815+ SiMustWriteLock(sb);
13816+
13817+ sbinfo = au_sbi(sb);
13818+ fhsm = &sbinfo->si_fhsm;
13819+ AuDebugOn(!fhsm);
13820+ fhsm->fhsm_bottom = bindex;
13821+}
13822+
13823+/* ---------------------------------------------------------------------- */
13824+
076b876e
AM
13825+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br)
13826+{
13827+ struct au_br_fhsm *bf;
13828+
13829+ bf = br->br_fhsm;
13830+ MtxMustLock(&bf->bf_lock);
13831+
13832+ return !bf->bf_readable
13833+ || time_after(jiffies,
13834+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire);
13835+}
13836+
13837+/* ---------------------------------------------------------------------- */
13838+
13839+static void au_fhsm_notify(struct super_block *sb, int val)
13840+{
13841+ struct au_sbinfo *sbinfo;
13842+ struct au_fhsm *fhsm;
13843+
13844+ SiMustAnyLock(sb);
13845+
13846+ sbinfo = au_sbi(sb);
13847+ fhsm = &sbinfo->si_fhsm;
13848+ if (au_fhsm_pid(fhsm)
13849+ && atomic_read(&fhsm->fhsm_readable) != -1) {
13850+ atomic_set(&fhsm->fhsm_readable, val);
13851+ if (val)
13852+ wake_up(&fhsm->fhsm_wqh);
13853+ }
13854+}
13855+
13856+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex,
13857+ struct aufs_stfs *rstfs, int do_lock, int do_notify)
13858+{
13859+ int err;
13860+ struct au_branch *br;
13861+ struct au_br_fhsm *bf;
13862+
13863+ br = au_sbr(sb, bindex);
13864+ AuDebugOn(au_br_rdonly(br));
13865+ bf = br->br_fhsm;
13866+ AuDebugOn(!bf);
13867+
13868+ if (do_lock)
13869+ mutex_lock(&bf->bf_lock);
13870+ else
13871+ MtxMustLock(&bf->bf_lock);
13872+
13873+ /* sb->s_root for NFS is unreliable */
13874+ err = au_br_stfs(br, &bf->bf_stfs);
13875+ if (unlikely(err)) {
13876+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err);
13877+ goto out;
13878+ }
13879+
13880+ bf->bf_jiffy = jiffies;
13881+ bf->bf_readable = 1;
13882+ if (do_notify)
13883+ au_fhsm_notify(sb, /*val*/1);
13884+ if (rstfs)
13885+ *rstfs = bf->bf_stfs;
13886+
13887+out:
13888+ if (do_lock)
13889+ mutex_unlock(&bf->bf_lock);
13890+ au_fhsm_notify(sb, /*val*/1);
13891+
13892+ return err;
13893+}
13894+
13895+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
13896+{
13897+ int err;
076b876e
AM
13898+ struct au_sbinfo *sbinfo;
13899+ struct au_fhsm *fhsm;
13900+ struct au_branch *br;
13901+ struct au_br_fhsm *bf;
13902+
13903+ AuDbg("b%d, force %d\n", bindex, force);
13904+ SiMustAnyLock(sb);
13905+
13906+ sbinfo = au_sbi(sb);
13907+ fhsm = &sbinfo->si_fhsm;
c1595e42
JR
13908+ if (!au_ftest_si(sbinfo, FHSM)
13909+ || fhsm->fhsm_bottom == bindex)
076b876e
AM
13910+ return;
13911+
13912+ br = au_sbr(sb, bindex);
13913+ bf = br->br_fhsm;
13914+ AuDebugOn(!bf);
13915+ mutex_lock(&bf->bf_lock);
13916+ if (force
13917+ || au_fhsm_pid(fhsm)
13918+ || au_fhsm_test_jiffy(sbinfo, br))
13919+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0,
13920+ /*do_notify*/1);
13921+ mutex_unlock(&bf->bf_lock);
13922+}
13923+
13924+void au_fhsm_wrote_all(struct super_block *sb, int force)
13925+{
5afbbe0d 13926+ aufs_bindex_t bindex, bbot;
076b876e
AM
13927+ struct au_branch *br;
13928+
13929+ /* exclude the bottom */
5afbbe0d
AM
13930+ bbot = au_fhsm_bottom(sb);
13931+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
13932+ br = au_sbr(sb, bindex);
13933+ if (au_br_fhsm(br->br_perm))
13934+ au_fhsm_wrote(sb, bindex, force);
13935+ }
13936+}
13937+
13938+/* ---------------------------------------------------------------------- */
13939+
be118d29 13940+static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait)
076b876e 13941+{
be118d29 13942+ __poll_t mask;
076b876e
AM
13943+ struct au_sbinfo *sbinfo;
13944+ struct au_fhsm *fhsm;
13945+
13946+ mask = 0;
13947+ sbinfo = file->private_data;
13948+ fhsm = &sbinfo->si_fhsm;
13949+ poll_wait(file, &fhsm->fhsm_wqh, wait);
13950+ if (atomic_read(&fhsm->fhsm_readable))
be118d29 13951+ mask = EPOLLIN /* | EPOLLRDNORM */;
076b876e 13952+
b00004a5
AM
13953+ if (!mask)
13954+ AuDbg("mask 0x%x\n", mask);
076b876e
AM
13955+ return mask;
13956+}
13957+
13958+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr,
13959+ struct aufs_stfs *stfs, __s16 brid)
13960+{
13961+ int err;
13962+
13963+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs));
13964+ if (!err)
13965+ err = __put_user(brid, &stbr->brid);
13966+ if (unlikely(err))
13967+ err = -EFAULT;
13968+
13969+ return err;
13970+}
13971+
13972+static ssize_t au_fhsm_do_read(struct super_block *sb,
13973+ struct aufs_stbr __user *stbr, size_t count)
13974+{
13975+ ssize_t err;
13976+ int nstbr;
5afbbe0d 13977+ aufs_bindex_t bindex, bbot;
076b876e
AM
13978+ struct au_branch *br;
13979+ struct au_br_fhsm *bf;
13980+
13981+ /* except the bottom branch */
13982+ err = 0;
13983+ nstbr = 0;
5afbbe0d
AM
13984+ bbot = au_fhsm_bottom(sb);
13985+ for (bindex = 0; !err && bindex < bbot; bindex++) {
076b876e
AM
13986+ br = au_sbr(sb, bindex);
13987+ if (!au_br_fhsm(br->br_perm))
13988+ continue;
13989+
13990+ bf = br->br_fhsm;
13991+ mutex_lock(&bf->bf_lock);
13992+ if (bf->bf_readable) {
13993+ err = -EFAULT;
13994+ if (count >= sizeof(*stbr))
13995+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs,
13996+ br->br_id);
13997+ if (!err) {
13998+ bf->bf_readable = 0;
13999+ count -= sizeof(*stbr);
14000+ nstbr++;
14001+ }
14002+ }
14003+ mutex_unlock(&bf->bf_lock);
14004+ }
14005+ if (!err)
14006+ err = sizeof(*stbr) * nstbr;
14007+
14008+ return err;
14009+}
14010+
14011+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count,
14012+ loff_t *pos)
14013+{
14014+ ssize_t err;
14015+ int readable;
5afbbe0d 14016+ aufs_bindex_t nfhsm, bindex, bbot;
076b876e
AM
14017+ struct au_sbinfo *sbinfo;
14018+ struct au_fhsm *fhsm;
14019+ struct au_branch *br;
14020+ struct super_block *sb;
14021+
14022+ err = 0;
14023+ sbinfo = file->private_data;
14024+ fhsm = &sbinfo->si_fhsm;
14025+need_data:
14026+ spin_lock_irq(&fhsm->fhsm_wqh.lock);
14027+ if (!atomic_read(&fhsm->fhsm_readable)) {
14028+ if (vfsub_file_flags(file) & O_NONBLOCK)
14029+ err = -EAGAIN;
14030+ else
14031+ err = wait_event_interruptible_locked_irq
14032+ (fhsm->fhsm_wqh,
14033+ atomic_read(&fhsm->fhsm_readable));
14034+ }
14035+ spin_unlock_irq(&fhsm->fhsm_wqh.lock);
14036+ if (unlikely(err))
14037+ goto out;
14038+
14039+ /* sb may already be dead */
14040+ au_rw_read_lock(&sbinfo->si_rwsem);
14041+ readable = atomic_read(&fhsm->fhsm_readable);
14042+ if (readable > 0) {
14043+ sb = sbinfo->si_sb;
14044+ AuDebugOn(!sb);
14045+ /* exclude the bottom branch */
14046+ nfhsm = 0;
5afbbe0d
AM
14047+ bbot = au_fhsm_bottom(sb);
14048+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
14049+ br = au_sbr(sb, bindex);
14050+ if (au_br_fhsm(br->br_perm))
14051+ nfhsm++;
14052+ }
14053+ err = -EMSGSIZE;
14054+ if (nfhsm * sizeof(struct aufs_stbr) <= count) {
14055+ atomic_set(&fhsm->fhsm_readable, 0);
14056+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf,
14057+ count);
14058+ }
14059+ }
14060+ au_rw_read_unlock(&sbinfo->si_rwsem);
14061+ if (!readable)
14062+ goto need_data;
14063+
14064+out:
14065+ return err;
14066+}
14067+
14068+static int au_fhsm_release(struct inode *inode, struct file *file)
14069+{
14070+ struct au_sbinfo *sbinfo;
14071+ struct au_fhsm *fhsm;
14072+
14073+ /* sb may already be dead */
14074+ sbinfo = file->private_data;
14075+ fhsm = &sbinfo->si_fhsm;
14076+ spin_lock(&fhsm->fhsm_spin);
14077+ fhsm->fhsm_pid = 0;
14078+ spin_unlock(&fhsm->fhsm_spin);
14079+ kobject_put(&sbinfo->si_kobj);
14080+
14081+ return 0;
14082+}
14083+
14084+static const struct file_operations au_fhsm_fops = {
14085+ .owner = THIS_MODULE,
14086+ .llseek = noop_llseek,
14087+ .read = au_fhsm_read,
14088+ .poll = au_fhsm_poll,
14089+ .release = au_fhsm_release
14090+};
14091+
14092+int au_fhsm_fd(struct super_block *sb, int oflags)
14093+{
14094+ int err, fd;
14095+ struct au_sbinfo *sbinfo;
14096+ struct au_fhsm *fhsm;
14097+
14098+ err = -EPERM;
14099+ if (unlikely(!capable(CAP_SYS_ADMIN)))
14100+ goto out;
14101+
14102+ err = -EINVAL;
14103+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK)))
14104+ goto out;
14105+
14106+ err = 0;
14107+ sbinfo = au_sbi(sb);
14108+ fhsm = &sbinfo->si_fhsm;
14109+ spin_lock(&fhsm->fhsm_spin);
14110+ if (!fhsm->fhsm_pid)
14111+ fhsm->fhsm_pid = current->pid;
14112+ else
14113+ err = -EBUSY;
14114+ spin_unlock(&fhsm->fhsm_spin);
14115+ if (unlikely(err))
14116+ goto out;
14117+
14118+ oflags |= O_RDONLY;
14119+ /* oflags |= FMODE_NONOTIFY; */
14120+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags);
14121+ err = fd;
14122+ if (unlikely(fd < 0))
14123+ goto out_pid;
14124+
acd2b654 14125+ /* succeed regardless 'fhsm' status */
076b876e
AM
14126+ kobject_get(&sbinfo->si_kobj);
14127+ si_noflush_read_lock(sb);
14128+ if (au_ftest_si(sbinfo, FHSM))
14129+ au_fhsm_wrote_all(sb, /*force*/0);
14130+ si_read_unlock(sb);
14131+ goto out; /* success */
14132+
14133+out_pid:
14134+ spin_lock(&fhsm->fhsm_spin);
14135+ fhsm->fhsm_pid = 0;
14136+ spin_unlock(&fhsm->fhsm_spin);
14137+out:
14138+ AuTraceErr(err);
14139+ return err;
14140+}
14141+
14142+/* ---------------------------------------------------------------------- */
14143+
14144+int au_fhsm_br_alloc(struct au_branch *br)
14145+{
14146+ int err;
14147+
14148+ err = 0;
14149+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS);
14150+ if (br->br_fhsm)
14151+ au_br_fhsm_init(br->br_fhsm);
14152+ else
14153+ err = -ENOMEM;
14154+
14155+ return err;
14156+}
14157+
14158+/* ---------------------------------------------------------------------- */
14159+
14160+void au_fhsm_fin(struct super_block *sb)
14161+{
14162+ au_fhsm_notify(sb, /*val*/-1);
14163+}
14164+
14165+void au_fhsm_init(struct au_sbinfo *sbinfo)
14166+{
14167+ struct au_fhsm *fhsm;
14168+
14169+ fhsm = &sbinfo->si_fhsm;
14170+ spin_lock_init(&fhsm->fhsm_spin);
14171+ init_waitqueue_head(&fhsm->fhsm_wqh);
14172+ atomic_set(&fhsm->fhsm_readable, 0);
14173+ fhsm->fhsm_expire
14174+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC);
c1595e42 14175+ fhsm->fhsm_bottom = -1;
076b876e
AM
14176+}
14177+
14178+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec)
14179+{
14180+ sbinfo->si_fhsm.fhsm_expire
14181+ = msecs_to_jiffies(sec * MSEC_PER_SEC);
14182+}
14183+
14184+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo)
14185+{
14186+ unsigned int u;
14187+
14188+ if (!au_ftest_si(sbinfo, FHSM))
14189+ return;
14190+
14191+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC;
14192+ if (u != AUFS_FHSM_CACHE_DEF_SEC)
14193+ seq_printf(seq, ",fhsm_sec=%u", u);
14194+}
7f207e10 14195diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
fbc438ed
JR
14196--- /usr/share/empty/fs/aufs/file.c 1970-01-01 08:00:00.000000000 +0800
14197+++ linux/fs/aufs/file.c 2019-07-11 21:21:54.379051070 +0800
acd2b654 14198@@ -0,0 +1,863 @@
cd7a4cd9 14199+// SPDX-License-Identifier: GPL-2.0
1facf9fc 14200+/*
ba1aed25 14201+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 14202+ *
14203+ * This program, aufs is free software; you can redistribute it and/or modify
14204+ * it under the terms of the GNU General Public License as published by
14205+ * the Free Software Foundation; either version 2 of the License, or
14206+ * (at your option) any later version.
dece6358
AM
14207+ *
14208+ * This program is distributed in the hope that it will be useful,
14209+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14210+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14211+ * GNU General Public License for more details.
14212+ *
14213+ * You should have received a copy of the GNU General Public License
523b37e3 14214+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 14215+ */
14216+
14217+/*
4a4d8108 14218+ * handling file/dir, and address_space operation
1facf9fc 14219+ */
14220+
7eafdf33
AM
14221+#ifdef CONFIG_AUFS_DEBUG
14222+#include <linux/migrate.h>
14223+#endif
4a4d8108 14224+#include <linux/pagemap.h>
1facf9fc 14225+#include "aufs.h"
14226+
4a4d8108
AM
14227+/* drop flags for writing */
14228+unsigned int au_file_roflags(unsigned int flags)
14229+{
14230+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
14231+ flags |= O_RDONLY | O_NOATIME;
14232+ return flags;
14233+}
14234+
14235+/* common functions to regular file and dir */
14236+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 14237+ struct file *file, int force_wr)
1facf9fc 14238+{
1308ab2a 14239+ struct file *h_file;
4a4d8108
AM
14240+ struct dentry *h_dentry;
14241+ struct inode *h_inode;
14242+ struct super_block *sb;
14243+ struct au_branch *br;
14244+ struct path h_path;
b912730e 14245+ int err;
1facf9fc 14246+
4a4d8108
AM
14247+ /* a race condition can happen between open and unlink/rmdir */
14248+ h_file = ERR_PTR(-ENOENT);
14249+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 14250+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry)))
4a4d8108 14251+ goto out;
5527c038 14252+ h_inode = d_inode(h_dentry);
027c5e7a
AM
14253+ spin_lock(&h_dentry->d_lock);
14254+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
5527c038 14255+ /* || !d_inode(dentry)->i_nlink */
027c5e7a
AM
14256+ ;
14257+ spin_unlock(&h_dentry->d_lock);
14258+ if (unlikely(err))
4a4d8108 14259+ goto out;
1facf9fc 14260+
4a4d8108
AM
14261+ sb = dentry->d_sb;
14262+ br = au_sbr(sb, bindex);
b912730e
AM
14263+ err = au_br_test_oflag(flags, br);
14264+ h_file = ERR_PTR(err);
14265+ if (unlikely(err))
027c5e7a 14266+ goto out;
1facf9fc 14267+
4a4d8108 14268+ /* drop flags for writing */
5527c038 14269+ if (au_test_ro(sb, bindex, d_inode(dentry))) {
392086de
AM
14270+ if (force_wr && !(flags & O_WRONLY))
14271+ force_wr = 0;
4a4d8108 14272+ flags = au_file_roflags(flags);
392086de
AM
14273+ if (force_wr) {
14274+ h_file = ERR_PTR(-EROFS);
14275+ flags = au_file_roflags(flags);
14276+ if (unlikely(vfsub_native_ro(h_inode)
14277+ || IS_APPEND(h_inode)))
14278+ goto out;
14279+ flags &= ~O_ACCMODE;
14280+ flags |= O_WRONLY;
14281+ }
14282+ }
4a4d8108 14283+ flags &= ~O_CREAT;
acd2b654 14284+ au_lcnt_inc(&br->br_nfiles);
4a4d8108 14285+ h_path.dentry = h_dentry;
86dc4139 14286+ h_path.mnt = au_br_mnt(br);
38d290e6 14287+ h_file = vfsub_dentry_open(&h_path, flags);
4a4d8108
AM
14288+ if (IS_ERR(h_file))
14289+ goto out_br;
dece6358 14290+
b912730e 14291+ if (flags & __FMODE_EXEC) {
4a4d8108
AM
14292+ err = deny_write_access(h_file);
14293+ if (unlikely(err)) {
14294+ fput(h_file);
14295+ h_file = ERR_PTR(err);
14296+ goto out_br;
14297+ }
14298+ }
953406b4 14299+ fsnotify_open(h_file);
4a4d8108 14300+ goto out; /* success */
1facf9fc 14301+
4f0767ce 14302+out_br:
acd2b654 14303+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 14304+out:
4a4d8108
AM
14305+ return h_file;
14306+}
1308ab2a 14307+
076b876e
AM
14308+static int au_cmoo(struct dentry *dentry)
14309+{
8b6a4947 14310+ int err, cmoo, matched;
076b876e
AM
14311+ unsigned int udba;
14312+ struct path h_path;
14313+ struct au_pin pin;
14314+ struct au_cp_generic cpg = {
14315+ .dentry = dentry,
14316+ .bdst = -1,
14317+ .bsrc = -1,
14318+ .len = -1,
14319+ .pin = &pin,
14320+ .flags = AuCpup_DTIME | AuCpup_HOPEN
14321+ };
7e9cd9fe 14322+ struct inode *delegated;
076b876e
AM
14323+ struct super_block *sb;
14324+ struct au_sbinfo *sbinfo;
14325+ struct au_fhsm *fhsm;
14326+ pid_t pid;
14327+ struct au_branch *br;
14328+ struct dentry *parent;
14329+ struct au_hinode *hdir;
14330+
14331+ DiMustWriteLock(dentry);
5527c038 14332+ IiMustWriteLock(d_inode(dentry));
076b876e
AM
14333+
14334+ err = 0;
14335+ if (IS_ROOT(dentry))
14336+ goto out;
5afbbe0d 14337+ cpg.bsrc = au_dbtop(dentry);
076b876e
AM
14338+ if (!cpg.bsrc)
14339+ goto out;
14340+
14341+ sb = dentry->d_sb;
14342+ sbinfo = au_sbi(sb);
14343+ fhsm = &sbinfo->si_fhsm;
14344+ pid = au_fhsm_pid(fhsm);
8b6a4947
AM
14345+ rcu_read_lock();
14346+ matched = (pid
14347+ && (current->pid == pid
14348+ || rcu_dereference(current->real_parent)->pid == pid));
14349+ rcu_read_unlock();
14350+ if (matched)
076b876e
AM
14351+ goto out;
14352+
14353+ br = au_sbr(sb, cpg.bsrc);
14354+ cmoo = au_br_cmoo(br->br_perm);
14355+ if (!cmoo)
14356+ goto out;
7e9cd9fe 14357+ if (!d_is_reg(dentry))
076b876e
AM
14358+ cmoo &= AuBrAttr_COO_ALL;
14359+ if (!cmoo)
14360+ goto out;
14361+
14362+ parent = dget_parent(dentry);
14363+ di_write_lock_parent(parent);
14364+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1);
14365+ cpg.bdst = err;
14366+ if (unlikely(err < 0)) {
14367+ err = 0; /* there is no upper writable branch */
14368+ goto out_dgrade;
14369+ }
14370+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst);
14371+
14372+ /* do not respect the coo attrib for the target branch */
14373+ err = au_cpup_dirs(dentry, cpg.bdst);
14374+ if (unlikely(err))
14375+ goto out_dgrade;
14376+
14377+ di_downgrade_lock(parent, AuLock_IR);
14378+ udba = au_opt_udba(sb);
14379+ err = au_pin(&pin, dentry, cpg.bdst, udba,
14380+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14381+ if (unlikely(err))
14382+ goto out_parent;
14383+
14384+ err = au_sio_cpup_simple(&cpg);
14385+ au_unpin(&pin);
14386+ if (unlikely(err))
14387+ goto out_parent;
14388+ if (!(cmoo & AuBrWAttr_MOO))
14389+ goto out_parent; /* success */
14390+
14391+ err = au_pin(&pin, dentry, cpg.bsrc, udba,
14392+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14393+ if (unlikely(err))
14394+ goto out_parent;
14395+
14396+ h_path.mnt = au_br_mnt(br);
14397+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc);
5527c038 14398+ hdir = au_hi(d_inode(parent), cpg.bsrc);
076b876e
AM
14399+ delegated = NULL;
14400+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1);
14401+ au_unpin(&pin);
14402+ /* todo: keep h_dentry or not? */
14403+ if (unlikely(err == -EWOULDBLOCK)) {
14404+ pr_warn("cannot retry for NFSv4 delegation"
14405+ " for an internal unlink\n");
14406+ iput(delegated);
14407+ }
14408+ if (unlikely(err)) {
14409+ pr_err("unlink %pd after coo failed (%d), ignored\n",
14410+ dentry, err);
14411+ err = 0;
14412+ }
14413+ goto out_parent; /* success */
14414+
14415+out_dgrade:
14416+ di_downgrade_lock(parent, AuLock_IR);
14417+out_parent:
14418+ di_read_unlock(parent, AuLock_IR);
14419+ dput(parent);
14420+out:
14421+ AuTraceErr(err);
14422+ return err;
14423+}
14424+
b912730e 14425+int au_do_open(struct file *file, struct au_do_open_args *args)
1facf9fc 14426+{
8b6a4947 14427+ int err, aopen = args->aopen;
1facf9fc 14428+ struct dentry *dentry;
076b876e 14429+ struct au_finfo *finfo;
1308ab2a 14430+
8b6a4947 14431+ if (!aopen)
b912730e
AM
14432+ err = au_finfo_init(file, args->fidir);
14433+ else {
14434+ lockdep_off();
14435+ err = au_finfo_init(file, args->fidir);
14436+ lockdep_on();
14437+ }
4a4d8108
AM
14438+ if (unlikely(err))
14439+ goto out;
1facf9fc 14440+
2000de60 14441+ dentry = file->f_path.dentry;
b912730e 14442+ AuDebugOn(IS_ERR_OR_NULL(dentry));
8b6a4947
AM
14443+ di_write_lock_child(dentry);
14444+ err = au_cmoo(dentry);
14445+ di_downgrade_lock(dentry, AuLock_IR);
14446+ if (!err) {
14447+ if (!aopen)
b912730e 14448+ err = args->open(file, vfsub_file_flags(file), NULL);
8b6a4947
AM
14449+ else {
14450+ lockdep_off();
acd2b654
AM
14451+ err = args->open(file, vfsub_file_flags(file),
14452+ args->h_file);
8b6a4947
AM
14453+ lockdep_on();
14454+ }
b912730e 14455+ }
8b6a4947 14456+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 14457+
076b876e
AM
14458+ finfo = au_fi(file);
14459+ if (!err) {
14460+ finfo->fi_file = file;
8b6a4947
AM
14461+ au_hbl_add(&finfo->fi_hlist,
14462+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
076b876e 14463+ }
8b6a4947 14464+ if (!aopen)
b912730e
AM
14465+ fi_write_unlock(file);
14466+ else {
14467+ lockdep_off();
14468+ fi_write_unlock(file);
14469+ lockdep_on();
14470+ }
4a4d8108 14471+ if (unlikely(err)) {
076b876e 14472+ finfo->fi_hdir = NULL;
1c60b727 14473+ au_finfo_fin(file);
1308ab2a 14474+ }
4a4d8108 14475+
4f0767ce 14476+out:
8b6a4947 14477+ AuTraceErr(err);
1308ab2a 14478+ return err;
14479+}
dece6358 14480+
4a4d8108 14481+int au_reopen_nondir(struct file *file)
1308ab2a 14482+{
4a4d8108 14483+ int err;
5afbbe0d 14484+ aufs_bindex_t btop;
4a4d8108 14485+ struct dentry *dentry;
acd2b654 14486+ struct au_branch *br;
4a4d8108 14487+ struct file *h_file, *h_file_tmp;
1308ab2a 14488+
2000de60 14489+ dentry = file->f_path.dentry;
5afbbe0d 14490+ btop = au_dbtop(dentry);
acd2b654 14491+ br = au_sbr(dentry->d_sb, btop);
4a4d8108 14492+ h_file_tmp = NULL;
5afbbe0d 14493+ if (au_fbtop(file) == btop) {
4a4d8108
AM
14494+ h_file = au_hf_top(file);
14495+ if (file->f_mode == h_file->f_mode)
14496+ return 0; /* success */
14497+ h_file_tmp = h_file;
14498+ get_file(h_file_tmp);
acd2b654 14499+ au_lcnt_inc(&br->br_nfiles);
5afbbe0d 14500+ au_set_h_fptr(file, btop, NULL);
4a4d8108
AM
14501+ }
14502+ AuDebugOn(au_fi(file)->fi_hdir);
86dc4139
AM
14503+ /*
14504+ * it can happen
14505+ * file exists on both of rw and ro
5afbbe0d 14506+ * open --> dbtop and fbtop are both 0
86dc4139
AM
14507+ * prepend a branch as rw, "rw" become ro
14508+ * remove rw/file
14509+ * delete the top branch, "rw" becomes rw again
5afbbe0d
AM
14510+ * --> dbtop is 1, fbtop is still 0
14511+ * write --> fbtop is 0 but dbtop is 1
86dc4139 14512+ */
5afbbe0d 14513+ /* AuDebugOn(au_fbtop(file) < btop); */
1308ab2a 14514+
5afbbe0d 14515+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC,
392086de 14516+ file, /*force_wr*/0);
4a4d8108 14517+ err = PTR_ERR(h_file);
86dc4139
AM
14518+ if (IS_ERR(h_file)) {
14519+ if (h_file_tmp) {
acd2b654 14520+ /* revert */
5afbbe0d 14521+ au_set_h_fptr(file, btop, h_file_tmp);
86dc4139
AM
14522+ h_file_tmp = NULL;
14523+ }
4a4d8108 14524+ goto out; /* todo: close all? */
86dc4139 14525+ }
4a4d8108
AM
14526+
14527+ err = 0;
5afbbe0d
AM
14528+ au_set_fbtop(file, btop);
14529+ au_set_h_fptr(file, btop, h_file);
4a4d8108
AM
14530+ au_update_figen(file);
14531+ /* todo: necessary? */
14532+ /* file->f_ra = h_file->f_ra; */
14533+
4f0767ce 14534+out:
acd2b654 14535+ if (h_file_tmp) {
4a4d8108 14536+ fput(h_file_tmp);
acd2b654
AM
14537+ au_lcnt_dec(&br->br_nfiles);
14538+ }
4a4d8108 14539+ return err;
1facf9fc 14540+}
14541+
1308ab2a 14542+/* ---------------------------------------------------------------------- */
14543+
4a4d8108
AM
14544+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
14545+ struct dentry *hi_wh)
1facf9fc 14546+{
4a4d8108 14547+ int err;
5afbbe0d 14548+ aufs_bindex_t btop;
4a4d8108
AM
14549+ struct au_dinfo *dinfo;
14550+ struct dentry *h_dentry;
14551+ struct au_hdentry *hdp;
1facf9fc 14552+
2000de60 14553+ dinfo = au_di(file->f_path.dentry);
4a4d8108 14554+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 14555+
5afbbe0d
AM
14556+ btop = dinfo->di_btop;
14557+ dinfo->di_btop = btgt;
14558+ hdp = au_hdentry(dinfo, btgt);
14559+ h_dentry = hdp->hd_dentry;
14560+ hdp->hd_dentry = hi_wh;
4a4d8108 14561+ err = au_reopen_nondir(file);
5afbbe0d
AM
14562+ hdp->hd_dentry = h_dentry;
14563+ dinfo->di_btop = btop;
1facf9fc 14564+
1facf9fc 14565+ return err;
14566+}
14567+
4a4d8108 14568+static int au_ready_to_write_wh(struct file *file, loff_t len,
86dc4139 14569+ aufs_bindex_t bcpup, struct au_pin *pin)
1facf9fc 14570+{
4a4d8108 14571+ int err;
027c5e7a 14572+ struct inode *inode, *h_inode;
c2b27bf2
AM
14573+ struct dentry *h_dentry, *hi_wh;
14574+ struct au_cp_generic cpg = {
2000de60 14575+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14576+ .bdst = bcpup,
14577+ .bsrc = -1,
14578+ .len = len,
14579+ .pin = pin
14580+ };
1facf9fc 14581+
5afbbe0d 14582+ au_update_dbtop(cpg.dentry);
5527c038 14583+ inode = d_inode(cpg.dentry);
027c5e7a 14584+ h_inode = NULL;
5afbbe0d
AM
14585+ if (au_dbtop(cpg.dentry) <= bcpup
14586+ && au_dbbot(cpg.dentry) >= bcpup) {
c2b27bf2 14587+ h_dentry = au_h_dptr(cpg.dentry, bcpup);
5527c038
JR
14588+ if (h_dentry && d_is_positive(h_dentry))
14589+ h_inode = d_inode(h_dentry);
027c5e7a 14590+ }
4a4d8108 14591+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 14592+ if (!hi_wh && !h_inode)
c2b27bf2 14593+ err = au_sio_cpup_wh(&cpg, file);
4a4d8108
AM
14594+ else
14595+ /* already copied-up after unlink */
14596+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 14597+
4a4d8108 14598+ if (!err
38d290e6
JR
14599+ && (inode->i_nlink > 1
14600+ || (inode->i_state & I_LINKABLE))
c2b27bf2
AM
14601+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK))
14602+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup));
1308ab2a 14603+
dece6358 14604+ return err;
1facf9fc 14605+}
14606+
4a4d8108
AM
14607+/*
14608+ * prepare the @file for writing.
14609+ */
14610+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 14611+{
4a4d8108 14612+ int err;
5afbbe0d 14613+ aufs_bindex_t dbtop;
c1595e42 14614+ struct dentry *parent;
86dc4139 14615+ struct inode *inode;
1facf9fc 14616+ struct super_block *sb;
4a4d8108 14617+ struct file *h_file;
c2b27bf2 14618+ struct au_cp_generic cpg = {
2000de60 14619+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14620+ .bdst = -1,
14621+ .bsrc = -1,
14622+ .len = len,
14623+ .pin = pin,
14624+ .flags = AuCpup_DTIME
14625+ };
1facf9fc 14626+
c2b27bf2 14627+ sb = cpg.dentry->d_sb;
5527c038 14628+ inode = d_inode(cpg.dentry);
5afbbe0d 14629+ cpg.bsrc = au_fbtop(file);
c2b27bf2 14630+ err = au_test_ro(sb, cpg.bsrc, inode);
4a4d8108 14631+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
c2b27bf2
AM
14632+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE,
14633+ /*flags*/0);
1facf9fc 14634+ goto out;
4a4d8108 14635+ }
1facf9fc 14636+
027c5e7a 14637+ /* need to cpup or reopen */
c2b27bf2 14638+ parent = dget_parent(cpg.dentry);
4a4d8108 14639+ di_write_lock_parent(parent);
c2b27bf2
AM
14640+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14641+ cpg.bdst = err;
4a4d8108
AM
14642+ if (unlikely(err < 0))
14643+ goto out_dgrade;
14644+ err = 0;
14645+
c2b27bf2
AM
14646+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) {
14647+ err = au_cpup_dirs(cpg.dentry, cpg.bdst);
1facf9fc 14648+ if (unlikely(err))
4a4d8108
AM
14649+ goto out_dgrade;
14650+ }
14651+
c2b27bf2 14652+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108
AM
14653+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14654+ if (unlikely(err))
14655+ goto out_dgrade;
14656+
5afbbe0d
AM
14657+ dbtop = au_dbtop(cpg.dentry);
14658+ if (dbtop <= cpg.bdst)
c2b27bf2 14659+ cpg.bsrc = cpg.bdst;
027c5e7a 14660+
5afbbe0d 14661+ if (dbtop <= cpg.bdst /* just reopen */
c2b27bf2 14662+ || !d_unhashed(cpg.dentry) /* copyup and reopen */
027c5e7a 14663+ ) {
392086de 14664+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0);
86dc4139 14665+ if (IS_ERR(h_file))
027c5e7a 14666+ err = PTR_ERR(h_file);
86dc4139 14667+ else {
027c5e7a 14668+ di_downgrade_lock(parent, AuLock_IR);
5afbbe0d 14669+ if (dbtop > cpg.bdst)
c2b27bf2 14670+ err = au_sio_cpup_simple(&cpg);
027c5e7a
AM
14671+ if (!err)
14672+ err = au_reopen_nondir(file);
c2b27bf2 14673+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file);
027c5e7a 14674+ }
027c5e7a
AM
14675+ } else { /* copyup as wh and reopen */
14676+ /*
14677+ * since writable hfsplus branch is not supported,
14678+ * h_open_pre/post() are unnecessary.
14679+ */
c2b27bf2 14680+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin);
4a4d8108 14681+ di_downgrade_lock(parent, AuLock_IR);
4a4d8108 14682+ }
4a4d8108
AM
14683+
14684+ if (!err) {
14685+ au_pin_set_parent_lflag(pin, /*lflag*/0);
14686+ goto out_dput; /* success */
14687+ }
14688+ au_unpin(pin);
14689+ goto out_unlock;
1facf9fc 14690+
4f0767ce 14691+out_dgrade:
4a4d8108 14692+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 14693+out_unlock:
4a4d8108 14694+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14695+out_dput:
4a4d8108 14696+ dput(parent);
4f0767ce 14697+out:
1facf9fc 14698+ return err;
14699+}
14700+
4a4d8108
AM
14701+/* ---------------------------------------------------------------------- */
14702+
14703+int au_do_flush(struct file *file, fl_owner_t id,
14704+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 14705+{
4a4d8108 14706+ int err;
1facf9fc 14707+ struct super_block *sb;
4a4d8108 14708+ struct inode *inode;
1facf9fc 14709+
c06a8ce3
AM
14710+ inode = file_inode(file);
14711+ sb = inode->i_sb;
4a4d8108
AM
14712+ si_noflush_read_lock(sb);
14713+ fi_read_lock(file);
b752ccd1 14714+ ii_read_lock_child(inode);
1facf9fc 14715+
4a4d8108
AM
14716+ err = flush(file, id);
14717+ au_cpup_attr_timesizes(inode);
1facf9fc 14718+
b752ccd1 14719+ ii_read_unlock(inode);
4a4d8108 14720+ fi_read_unlock(file);
1308ab2a 14721+ si_read_unlock(sb);
dece6358 14722+ return err;
1facf9fc 14723+}
14724+
4a4d8108
AM
14725+/* ---------------------------------------------------------------------- */
14726+
14727+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 14728+{
4a4d8108 14729+ int err;
4a4d8108
AM
14730+ struct au_pin pin;
14731+ struct au_finfo *finfo;
c2b27bf2 14732+ struct dentry *parent, *hi_wh;
4a4d8108 14733+ struct inode *inode;
1facf9fc 14734+ struct super_block *sb;
c2b27bf2 14735+ struct au_cp_generic cpg = {
2000de60 14736+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14737+ .bdst = -1,
14738+ .bsrc = -1,
14739+ .len = -1,
14740+ .pin = &pin,
14741+ .flags = AuCpup_DTIME
14742+ };
1facf9fc 14743+
4a4d8108
AM
14744+ FiMustWriteLock(file);
14745+
14746+ err = 0;
14747+ finfo = au_fi(file);
c2b27bf2 14748+ sb = cpg.dentry->d_sb;
5527c038 14749+ inode = d_inode(cpg.dentry);
5afbbe0d 14750+ cpg.bdst = au_ibtop(inode);
c2b27bf2 14751+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry))
1308ab2a 14752+ goto out;
dece6358 14753+
c2b27bf2
AM
14754+ parent = dget_parent(cpg.dentry);
14755+ if (au_test_ro(sb, cpg.bdst, inode)) {
4a4d8108 14756+ di_read_lock_parent(parent, !AuLock_IR);
c2b27bf2
AM
14757+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14758+ cpg.bdst = err;
4a4d8108
AM
14759+ di_read_unlock(parent, !AuLock_IR);
14760+ if (unlikely(err < 0))
14761+ goto out_parent;
14762+ err = 0;
1facf9fc 14763+ }
1facf9fc 14764+
4a4d8108 14765+ di_read_lock_parent(parent, AuLock_IR);
c2b27bf2 14766+ hi_wh = au_hi_wh(inode, cpg.bdst);
7f207e10
AM
14767+ if (!S_ISDIR(inode->i_mode)
14768+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108 14769+ && au_plink_test(inode)
c2b27bf2 14770+ && !d_unhashed(cpg.dentry)
5afbbe0d 14771+ && cpg.bdst < au_dbtop(cpg.dentry)) {
c2b27bf2 14772+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst);
4a4d8108
AM
14773+ if (unlikely(err))
14774+ goto out_unlock;
14775+
14776+ /* always superio. */
c2b27bf2 14777+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108 14778+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 14779+ if (!err) {
c2b27bf2 14780+ err = au_sio_cpup_simple(&cpg);
367653fa
AM
14781+ au_unpin(&pin);
14782+ }
4a4d8108
AM
14783+ } else if (hi_wh) {
14784+ /* already copied-up after unlink */
c2b27bf2 14785+ err = au_reopen_wh(file, cpg.bdst, hi_wh);
4a4d8108
AM
14786+ *need_reopen = 0;
14787+ }
1facf9fc 14788+
4f0767ce 14789+out_unlock:
4a4d8108 14790+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14791+out_parent:
4a4d8108 14792+ dput(parent);
4f0767ce 14793+out:
1308ab2a 14794+ return err;
dece6358 14795+}
1facf9fc 14796+
4a4d8108 14797+static void au_do_refresh_dir(struct file *file)
dece6358 14798+{
5afbbe0d 14799+ aufs_bindex_t bindex, bbot, new_bindex, brid;
4a4d8108
AM
14800+ struct au_hfile *p, tmp, *q;
14801+ struct au_finfo *finfo;
1308ab2a 14802+ struct super_block *sb;
4a4d8108 14803+ struct au_fidir *fidir;
1facf9fc 14804+
4a4d8108 14805+ FiMustWriteLock(file);
1facf9fc 14806+
2000de60 14807+ sb = file->f_path.dentry->d_sb;
4a4d8108
AM
14808+ finfo = au_fi(file);
14809+ fidir = finfo->fi_hdir;
14810+ AuDebugOn(!fidir);
14811+ p = fidir->fd_hfile + finfo->fi_btop;
14812+ brid = p->hf_br->br_id;
5afbbe0d
AM
14813+ bbot = fidir->fd_bbot;
14814+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) {
4a4d8108
AM
14815+ if (!p->hf_file)
14816+ continue;
1308ab2a 14817+
4a4d8108
AM
14818+ new_bindex = au_br_index(sb, p->hf_br->br_id);
14819+ if (new_bindex == bindex)
14820+ continue;
14821+ if (new_bindex < 0) {
14822+ au_set_h_fptr(file, bindex, NULL);
14823+ continue;
14824+ }
1308ab2a 14825+
4a4d8108
AM
14826+ /* swap two lower inode, and loop again */
14827+ q = fidir->fd_hfile + new_bindex;
14828+ tmp = *q;
14829+ *q = *p;
14830+ *p = tmp;
14831+ if (tmp.hf_file) {
14832+ bindex--;
14833+ p--;
14834+ }
14835+ }
1308ab2a 14836+
4a4d8108 14837+ p = fidir->fd_hfile;
2000de60 14838+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) {
5afbbe0d
AM
14839+ bbot = au_sbbot(sb);
14840+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot;
4a4d8108
AM
14841+ finfo->fi_btop++, p++)
14842+ if (p->hf_file) {
c06a8ce3 14843+ if (file_inode(p->hf_file))
4a4d8108 14844+ break;
1c60b727 14845+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14846+ }
14847+ } else {
5afbbe0d
AM
14848+ bbot = au_br_index(sb, brid);
14849+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot;
4a4d8108
AM
14850+ finfo->fi_btop++, p++)
14851+ if (p->hf_file)
1c60b727 14852+ au_hfput(p, /*execed*/0);
5afbbe0d 14853+ bbot = au_sbbot(sb);
4a4d8108 14854+ }
1308ab2a 14855+
5afbbe0d
AM
14856+ p = fidir->fd_hfile + bbot;
14857+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop;
4a4d8108
AM
14858+ fidir->fd_bbot--, p--)
14859+ if (p->hf_file) {
c06a8ce3 14860+ if (file_inode(p->hf_file))
4a4d8108 14861+ break;
1c60b727 14862+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14863+ }
14864+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 14865+}
14866+
4a4d8108
AM
14867+/*
14868+ * after branch manipulating, refresh the file.
14869+ */
14870+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 14871+{
e2f27e51 14872+ int err, need_reopen, nbr;
5afbbe0d 14873+ aufs_bindex_t bbot, bindex;
4a4d8108 14874+ struct dentry *dentry;
e2f27e51 14875+ struct super_block *sb;
1308ab2a 14876+ struct au_finfo *finfo;
4a4d8108 14877+ struct au_hfile *hfile;
1facf9fc 14878+
2000de60 14879+ dentry = file->f_path.dentry;
e2f27e51
AM
14880+ sb = dentry->d_sb;
14881+ nbr = au_sbbot(sb) + 1;
1308ab2a 14882+ finfo = au_fi(file);
4a4d8108
AM
14883+ if (!finfo->fi_hdir) {
14884+ hfile = &finfo->fi_htop;
14885+ AuDebugOn(!hfile->hf_file);
e2f27e51 14886+ bindex = au_br_index(sb, hfile->hf_br->br_id);
4a4d8108
AM
14887+ AuDebugOn(bindex < 0);
14888+ if (bindex != finfo->fi_btop)
5afbbe0d 14889+ au_set_fbtop(file, bindex);
4a4d8108 14890+ } else {
e2f27e51 14891+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0);
4a4d8108
AM
14892+ if (unlikely(err))
14893+ goto out;
14894+ au_do_refresh_dir(file);
14895+ }
1facf9fc 14896+
4a4d8108
AM
14897+ err = 0;
14898+ need_reopen = 1;
14899+ if (!au_test_mmapped(file))
14900+ err = au_file_refresh_by_inode(file, &need_reopen);
e2f27e51
AM
14901+ if (finfo->fi_hdir)
14902+ /* harmless if err */
14903+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1);
027c5e7a 14904+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
14905+ err = reopen(file);
14906+ if (!err) {
14907+ au_update_figen(file);
14908+ goto out; /* success */
14909+ }
14910+
14911+ /* error, close all lower files */
14912+ if (finfo->fi_hdir) {
5afbbe0d
AM
14913+ bbot = au_fbbot_dir(file);
14914+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++)
4a4d8108
AM
14915+ au_set_h_fptr(file, bindex, NULL);
14916+ }
1facf9fc 14917+
4f0767ce 14918+out:
1facf9fc 14919+ return err;
14920+}
14921+
4a4d8108
AM
14922+/* common function to regular file and dir */
14923+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 14924+ int wlock, unsigned int fi_lsc)
dece6358 14925+{
1308ab2a 14926+ int err;
4a4d8108 14927+ unsigned int sigen, figen;
5afbbe0d 14928+ aufs_bindex_t btop;
4a4d8108
AM
14929+ unsigned char pseudo_link;
14930+ struct dentry *dentry;
14931+ struct inode *inode;
1facf9fc 14932+
4a4d8108 14933+ err = 0;
2000de60 14934+ dentry = file->f_path.dentry;
5527c038 14935+ inode = d_inode(dentry);
4a4d8108 14936+ sigen = au_sigen(dentry->d_sb);
521ced18 14937+ fi_write_lock_nested(file, fi_lsc);
4a4d8108 14938+ figen = au_figen(file);
521ced18
JR
14939+ if (!fi_lsc)
14940+ di_write_lock_child(dentry);
14941+ else
14942+ di_write_lock_child2(dentry);
5afbbe0d
AM
14943+ btop = au_dbtop(dentry);
14944+ pseudo_link = (btop != au_ibtop(inode));
14945+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) {
4a4d8108
AM
14946+ if (!wlock) {
14947+ di_downgrade_lock(dentry, AuLock_IR);
14948+ fi_downgrade_lock(file);
14949+ }
14950+ goto out; /* success */
14951+ }
dece6358 14952+
4a4d8108 14953+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 14954+ if (au_digen_test(dentry, sigen)) {
4a4d8108 14955+ err = au_reval_dpath(dentry, sigen);
027c5e7a 14956+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 14957+ }
dece6358 14958+
027c5e7a
AM
14959+ if (!err)
14960+ err = refresh_file(file, reopen);
4a4d8108
AM
14961+ if (!err) {
14962+ if (!wlock) {
14963+ di_downgrade_lock(dentry, AuLock_IR);
14964+ fi_downgrade_lock(file);
14965+ }
14966+ } else {
14967+ di_write_unlock(dentry);
14968+ fi_write_unlock(file);
14969+ }
1facf9fc 14970+
4f0767ce 14971+out:
1308ab2a 14972+ return err;
14973+}
1facf9fc 14974+
4a4d8108
AM
14975+/* ---------------------------------------------------------------------- */
14976+
14977+/* cf. aufs_nopage() */
14978+/* for madvise(2) */
14979+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 14980+{
4a4d8108
AM
14981+ unlock_page(page);
14982+ return 0;
14983+}
1facf9fc 14984+
4a4d8108 14985+/* it will never be called, but necessary to support O_DIRECT */
5afbbe0d 14986+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
4a4d8108 14987+{ BUG(); return 0; }
1facf9fc 14988+
4a4d8108
AM
14989+/* they will never be called. */
14990+#ifdef CONFIG_AUFS_DEBUG
14991+static int aufs_write_begin(struct file *file, struct address_space *mapping,
14992+ loff_t pos, unsigned len, unsigned flags,
14993+ struct page **pagep, void **fsdata)
14994+{ AuUnsupport(); return 0; }
14995+static int aufs_write_end(struct file *file, struct address_space *mapping,
14996+ loff_t pos, unsigned len, unsigned copied,
14997+ struct page *page, void *fsdata)
14998+{ AuUnsupport(); return 0; }
14999+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
15000+{ AuUnsupport(); return 0; }
1308ab2a 15001+
4a4d8108
AM
15002+static int aufs_set_page_dirty(struct page *page)
15003+{ AuUnsupport(); return 0; }
392086de
AM
15004+static void aufs_invalidatepage(struct page *page, unsigned int offset,
15005+ unsigned int length)
4a4d8108
AM
15006+{ AuUnsupport(); }
15007+static int aufs_releasepage(struct page *page, gfp_t gfp)
15008+{ AuUnsupport(); return 0; }
79b8bda9 15009+#if 0 /* called by memory compaction regardless file */
4a4d8108 15010+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 15011+ struct page *page, enum migrate_mode mode)
4a4d8108 15012+{ AuUnsupport(); return 0; }
79b8bda9 15013+#endif
e2f27e51
AM
15014+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode)
15015+{ AuUnsupport(); return true; }
15016+static void aufs_putback_page(struct page *page)
15017+{ AuUnsupport(); }
4a4d8108
AM
15018+static int aufs_launder_page(struct page *page)
15019+{ AuUnsupport(); return 0; }
15020+static int aufs_is_partially_uptodate(struct page *page,
38d290e6
JR
15021+ unsigned long from,
15022+ unsigned long count)
4a4d8108 15023+{ AuUnsupport(); return 0; }
392086de
AM
15024+static void aufs_is_dirty_writeback(struct page *page, bool *dirty,
15025+ bool *writeback)
15026+{ AuUnsupport(); }
4a4d8108
AM
15027+static int aufs_error_remove_page(struct address_space *mapping,
15028+ struct page *page)
15029+{ AuUnsupport(); return 0; }
b4510431
AM
15030+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
15031+ sector_t *span)
15032+{ AuUnsupport(); return 0; }
15033+static void aufs_swap_deactivate(struct file *file)
15034+{ AuUnsupport(); }
4a4d8108
AM
15035+#endif /* CONFIG_AUFS_DEBUG */
15036+
15037+const struct address_space_operations aufs_aop = {
15038+ .readpage = aufs_readpage,
15039+ .direct_IO = aufs_direct_IO,
4a4d8108
AM
15040+#ifdef CONFIG_AUFS_DEBUG
15041+ .writepage = aufs_writepage,
4a4d8108
AM
15042+ /* no writepages, because of writepage */
15043+ .set_page_dirty = aufs_set_page_dirty,
15044+ /* no readpages, because of readpage */
15045+ .write_begin = aufs_write_begin,
15046+ .write_end = aufs_write_end,
15047+ /* no bmap, no block device */
15048+ .invalidatepage = aufs_invalidatepage,
15049+ .releasepage = aufs_releasepage,
79b8bda9
AM
15050+ /* is fallback_migrate_page ok? */
15051+ /* .migratepage = aufs_migratepage, */
e2f27e51
AM
15052+ .isolate_page = aufs_isolate_page,
15053+ .putback_page = aufs_putback_page,
4a4d8108
AM
15054+ .launder_page = aufs_launder_page,
15055+ .is_partially_uptodate = aufs_is_partially_uptodate,
392086de 15056+ .is_dirty_writeback = aufs_is_dirty_writeback,
b4510431
AM
15057+ .error_remove_page = aufs_error_remove_page,
15058+ .swap_activate = aufs_swap_activate,
15059+ .swap_deactivate = aufs_swap_deactivate
4a4d8108 15060+#endif /* CONFIG_AUFS_DEBUG */
dece6358 15061+};
7f207e10 15062diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
fbc438ed
JR
15063--- /usr/share/empty/fs/aufs/file.h 1970-01-01 08:00:00.000000000 +0800
15064+++ linux/fs/aufs/file.h 2019-07-11 21:21:54.379051070 +0800
9f237c51 15065@@ -0,0 +1,342 @@
062440b3 15066+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 15067+/*
ba1aed25 15068+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
15069+ *
15070+ * This program, aufs is free software; you can redistribute it and/or modify
15071+ * it under the terms of the GNU General Public License as published by
15072+ * the Free Software Foundation; either version 2 of the License, or
15073+ * (at your option) any later version.
15074+ *
15075+ * This program is distributed in the hope that it will be useful,
15076+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15077+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15078+ * GNU General Public License for more details.
15079+ *
15080+ * You should have received a copy of the GNU General Public License
523b37e3 15081+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 15082+ */
1facf9fc 15083+
4a4d8108
AM
15084+/*
15085+ * file operations
15086+ */
1facf9fc 15087+
4a4d8108
AM
15088+#ifndef __AUFS_FILE_H__
15089+#define __AUFS_FILE_H__
1facf9fc 15090+
4a4d8108 15091+#ifdef __KERNEL__
1facf9fc 15092+
2cbb1c4b 15093+#include <linux/file.h>
4a4d8108 15094+#include <linux/fs.h>
3c1bdaff 15095+#include <linux/mm_types.h>
4a4d8108 15096+#include <linux/poll.h>
4a4d8108 15097+#include "rwsem.h"
1facf9fc 15098+
4a4d8108
AM
15099+struct au_branch;
15100+struct au_hfile {
15101+ struct file *hf_file;
15102+ struct au_branch *hf_br;
15103+};
1facf9fc 15104+
4a4d8108
AM
15105+struct au_vdir;
15106+struct au_fidir {
15107+ aufs_bindex_t fd_bbot;
15108+ aufs_bindex_t fd_nent;
15109+ struct au_vdir *fd_vdir_cache;
15110+ struct au_hfile fd_hfile[];
15111+};
1facf9fc 15112+
4a4d8108 15113+static inline int au_fidir_sz(int nent)
dece6358 15114+{
4f0767ce
JR
15115+ AuDebugOn(nent < 0);
15116+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 15117+}
1facf9fc 15118+
4a4d8108
AM
15119+struct au_finfo {
15120+ atomic_t fi_generation;
dece6358 15121+
4a4d8108
AM
15122+ struct au_rwsem fi_rwsem;
15123+ aufs_bindex_t fi_btop;
15124+
15125+ /* do not union them */
15126+ struct { /* for non-dir */
15127+ struct au_hfile fi_htop;
2cbb1c4b 15128+ atomic_t fi_mmapped;
4a4d8108
AM
15129+ };
15130+ struct au_fidir *fi_hdir; /* for dir only */
523b37e3 15131+
8b6a4947 15132+ struct hlist_bl_node fi_hlist;
1c60b727 15133+ struct file *fi_file; /* very ugly */
9f237c51 15134+ struct rcu_head rcu;
4a4d8108 15135+} ____cacheline_aligned_in_smp;
1facf9fc 15136+
4a4d8108 15137+/* ---------------------------------------------------------------------- */
1facf9fc 15138+
4a4d8108
AM
15139+/* file.c */
15140+extern const struct address_space_operations aufs_aop;
15141+unsigned int au_file_roflags(unsigned int flags);
15142+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 15143+ struct file *file, int force_wr);
b912730e 15144+struct au_do_open_args {
8b6a4947 15145+ int aopen;
b912730e
AM
15146+ int (*open)(struct file *file, int flags,
15147+ struct file *h_file);
15148+ struct au_fidir *fidir;
15149+ struct file *h_file;
15150+};
15151+int au_do_open(struct file *file, struct au_do_open_args *args);
4a4d8108
AM
15152+int au_reopen_nondir(struct file *file);
15153+struct au_pin;
15154+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
15155+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 15156+ int wlock, unsigned int fi_lsc);
4a4d8108
AM
15157+int au_do_flush(struct file *file, fl_owner_t id,
15158+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 15159+
4a4d8108
AM
15160+/* poll.c */
15161+#ifdef CONFIG_AUFS_POLL
cd7a4cd9 15162+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt);
4a4d8108 15163+#endif
1facf9fc 15164+
4a4d8108
AM
15165+#ifdef CONFIG_AUFS_BR_HFSPLUS
15166+/* hfsplus.c */
392086de
AM
15167+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
15168+ int force_wr);
4a4d8108
AM
15169+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
15170+ struct file *h_file);
15171+#else
c1595e42
JR
15172+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
15173+ aufs_bindex_t bindex, int force_wr)
4a4d8108
AM
15174+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
15175+ struct file *h_file);
15176+#endif
1facf9fc 15177+
4a4d8108
AM
15178+/* f_op.c */
15179+extern const struct file_operations aufs_file_fop;
b912730e 15180+int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
4a4d8108 15181+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
521ced18 15182+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc);
4a4d8108 15183+
4a4d8108 15184+/* finfo.c */
f0c0a007 15185+void au_hfput(struct au_hfile *hf, int execed);
4a4d8108
AM
15186+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
15187+ struct file *h_file);
1facf9fc 15188+
4a4d8108 15189+void au_update_figen(struct file *file);
4a4d8108 15190+struct au_fidir *au_fidir_alloc(struct super_block *sb);
e2f27e51 15191+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
1facf9fc 15192+
4a4d8108 15193+void au_fi_init_once(void *_fi);
1c60b727 15194+void au_finfo_fin(struct file *file);
4a4d8108 15195+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 15196+
4a4d8108
AM
15197+/* ioctl.c */
15198+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
15199+#ifdef CONFIG_COMPAT
15200+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15201+ unsigned long arg);
c2b27bf2
AM
15202+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15203+ unsigned long arg);
b752ccd1 15204+#endif
1facf9fc 15205+
4a4d8108 15206+/* ---------------------------------------------------------------------- */
1facf9fc 15207+
4a4d8108
AM
15208+static inline struct au_finfo *au_fi(struct file *file)
15209+{
38d290e6 15210+ return file->private_data;
4a4d8108 15211+}
1facf9fc 15212+
4a4d8108 15213+/* ---------------------------------------------------------------------- */
1facf9fc 15214+
8b6a4947
AM
15215+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem)
15216+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem)
15217+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem)
15218+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem)
4a4d8108 15219+/*
8b6a4947
AM
15220+#define fi_read_trylock_nested(f) \
15221+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem)
15222+#define fi_write_trylock_nested(f) \
15223+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem)
15224+*/
15225+
15226+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem)
15227+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem)
15228+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem)
1308ab2a 15229+
521ced18
JR
15230+/* lock subclass for finfo */
15231+enum {
15232+ AuLsc_FI_1,
15233+ AuLsc_FI_2
15234+};
15235+
15236+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc)
15237+{
15238+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15239+}
15240+
15241+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc)
15242+{
15243+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15244+}
15245+
15246+/*
15247+ * fi_read_lock_1, fi_write_lock_1,
15248+ * fi_read_lock_2, fi_write_lock_2
15249+ */
15250+#define AuReadLockFunc(name) \
15251+static inline void fi_read_lock_##name(struct file *f) \
15252+{ fi_read_lock_nested(f, AuLsc_FI_##name); }
15253+
15254+#define AuWriteLockFunc(name) \
15255+static inline void fi_write_lock_##name(struct file *f) \
15256+{ fi_write_lock_nested(f, AuLsc_FI_##name); }
15257+
15258+#define AuRWLockFuncs(name) \
15259+ AuReadLockFunc(name) \
15260+ AuWriteLockFunc(name)
15261+
15262+AuRWLockFuncs(1);
15263+AuRWLockFuncs(2);
15264+
15265+#undef AuReadLockFunc
15266+#undef AuWriteLockFunc
15267+#undef AuRWLockFuncs
15268+
4a4d8108
AM
15269+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
15270+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
15271+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 15272+
1308ab2a 15273+/* ---------------------------------------------------------------------- */
15274+
4a4d8108 15275+/* todo: hard/soft set? */
5afbbe0d 15276+static inline aufs_bindex_t au_fbtop(struct file *file)
dece6358 15277+{
4a4d8108
AM
15278+ FiMustAnyLock(file);
15279+ return au_fi(file)->fi_btop;
15280+}
dece6358 15281+
5afbbe0d 15282+static inline aufs_bindex_t au_fbbot_dir(struct file *file)
4a4d8108
AM
15283+{
15284+ FiMustAnyLock(file);
15285+ AuDebugOn(!au_fi(file)->fi_hdir);
15286+ return au_fi(file)->fi_hdir->fd_bbot;
15287+}
1facf9fc 15288+
4a4d8108
AM
15289+static inline struct au_vdir *au_fvdir_cache(struct file *file)
15290+{
15291+ FiMustAnyLock(file);
15292+ AuDebugOn(!au_fi(file)->fi_hdir);
15293+ return au_fi(file)->fi_hdir->fd_vdir_cache;
15294+}
1facf9fc 15295+
5afbbe0d 15296+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15297+{
15298+ FiMustWriteLock(file);
15299+ au_fi(file)->fi_btop = bindex;
15300+}
1facf9fc 15301+
5afbbe0d 15302+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15303+{
15304+ FiMustWriteLock(file);
15305+ AuDebugOn(!au_fi(file)->fi_hdir);
15306+ au_fi(file)->fi_hdir->fd_bbot = bindex;
15307+}
1308ab2a 15308+
4a4d8108
AM
15309+static inline void au_set_fvdir_cache(struct file *file,
15310+ struct au_vdir *vdir_cache)
15311+{
15312+ FiMustWriteLock(file);
15313+ AuDebugOn(!au_fi(file)->fi_hdir);
15314+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
15315+}
dece6358 15316+
4a4d8108
AM
15317+static inline struct file *au_hf_top(struct file *file)
15318+{
15319+ FiMustAnyLock(file);
15320+ AuDebugOn(au_fi(file)->fi_hdir);
15321+ return au_fi(file)->fi_htop.hf_file;
15322+}
1facf9fc 15323+
4a4d8108
AM
15324+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
15325+{
15326+ FiMustAnyLock(file);
15327+ AuDebugOn(!au_fi(file)->fi_hdir);
15328+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
15329+}
15330+
4a4d8108
AM
15331+/* todo: memory barrier? */
15332+static inline unsigned int au_figen(struct file *f)
dece6358 15333+{
4a4d8108
AM
15334+ return atomic_read(&au_fi(f)->fi_generation);
15335+}
dece6358 15336+
2cbb1c4b
JR
15337+static inline void au_set_mmapped(struct file *f)
15338+{
15339+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
15340+ return;
0c3ec466 15341+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
15342+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
15343+ ;
15344+}
15345+
15346+static inline void au_unset_mmapped(struct file *f)
15347+{
15348+ atomic_dec(&au_fi(f)->fi_mmapped);
15349+}
15350+
4a4d8108
AM
15351+static inline int au_test_mmapped(struct file *f)
15352+{
2cbb1c4b
JR
15353+ return atomic_read(&au_fi(f)->fi_mmapped);
15354+}
15355+
15356+/* customize vma->vm_file */
15357+
15358+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
15359+ struct file *file)
15360+{
53392da6
AM
15361+ struct file *f;
15362+
15363+ f = vma->vm_file;
2cbb1c4b
JR
15364+ get_file(file);
15365+ vma->vm_file = file;
53392da6 15366+ fput(f);
2cbb1c4b
JR
15367+}
15368+
15369+#ifdef CONFIG_MMU
15370+#define AuDbgVmRegion(file, vma) do {} while (0)
15371+
15372+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15373+ struct file *file)
15374+{
15375+ au_do_vm_file_reset(vma, file);
15376+}
15377+#else
15378+#define AuDbgVmRegion(file, vma) \
15379+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
15380+
15381+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15382+ struct file *file)
15383+{
53392da6
AM
15384+ struct file *f;
15385+
2cbb1c4b 15386+ au_do_vm_file_reset(vma, file);
53392da6 15387+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
15388+ get_file(file);
15389+ vma->vm_region->vm_file = file;
53392da6 15390+ fput(f);
2cbb1c4b
JR
15391+}
15392+#endif /* CONFIG_MMU */
15393+
15394+/* handle vma->vm_prfile */
fb47a38f 15395+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
2cbb1c4b
JR
15396+ struct file *file)
15397+{
2cbb1c4b
JR
15398+ get_file(file);
15399+ vma->vm_prfile = file;
15400+#ifndef CONFIG_MMU
15401+ get_file(file);
15402+ vma->vm_region->vm_prfile = file;
15403+#endif
fb47a38f 15404+}
1308ab2a 15405+
4a4d8108
AM
15406+#endif /* __KERNEL__ */
15407+#endif /* __AUFS_FILE_H__ */
7f207e10 15408diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
fbc438ed
JR
15409--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 08:00:00.000000000 +0800
15410+++ linux/fs/aufs/finfo.c 2019-07-11 21:21:54.379051070 +0800
062440b3 15411@@ -0,0 +1,149 @@
cd7a4cd9 15412+// SPDX-License-Identifier: GPL-2.0
4a4d8108 15413+/*
ba1aed25 15414+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
15415+ *
15416+ * This program, aufs is free software; you can redistribute it and/or modify
15417+ * it under the terms of the GNU General Public License as published by
15418+ * the Free Software Foundation; either version 2 of the License, or
15419+ * (at your option) any later version.
15420+ *
15421+ * This program is distributed in the hope that it will be useful,
15422+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15423+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15424+ * GNU General Public License for more details.
15425+ *
15426+ * You should have received a copy of the GNU General Public License
523b37e3 15427+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 15428+ */
1308ab2a 15429+
4a4d8108
AM
15430+/*
15431+ * file private data
15432+ */
1facf9fc 15433+
4a4d8108 15434+#include "aufs.h"
1facf9fc 15435+
f0c0a007 15436+void au_hfput(struct au_hfile *hf, int execed)
4a4d8108 15437+{
f0c0a007 15438+ if (execed)
4a4d8108
AM
15439+ allow_write_access(hf->hf_file);
15440+ fput(hf->hf_file);
15441+ hf->hf_file = NULL;
acd2b654 15442+ au_lcnt_dec(&hf->hf_br->br_nfiles);
4a4d8108
AM
15443+ hf->hf_br = NULL;
15444+}
1facf9fc 15445+
4a4d8108
AM
15446+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
15447+{
15448+ struct au_finfo *finfo = au_fi(file);
15449+ struct au_hfile *hf;
15450+ struct au_fidir *fidir;
15451+
15452+ fidir = finfo->fi_hdir;
15453+ if (!fidir) {
15454+ AuDebugOn(finfo->fi_btop != bindex);
15455+ hf = &finfo->fi_htop;
15456+ } else
15457+ hf = fidir->fd_hfile + bindex;
15458+
15459+ if (hf && hf->hf_file)
f0c0a007 15460+ au_hfput(hf, vfsub_file_execed(file));
4a4d8108
AM
15461+ if (val) {
15462+ FiMustWriteLock(file);
b912730e 15463+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry));
4a4d8108 15464+ hf->hf_file = val;
2000de60 15465+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex);
1308ab2a 15466+ }
4a4d8108 15467+}
1facf9fc 15468+
4a4d8108
AM
15469+void au_update_figen(struct file *file)
15470+{
2000de60 15471+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry));
4a4d8108 15472+ /* smp_mb(); */ /* atomic_set */
1facf9fc 15473+}
15474+
4a4d8108
AM
15475+/* ---------------------------------------------------------------------- */
15476+
4a4d8108
AM
15477+struct au_fidir *au_fidir_alloc(struct super_block *sb)
15478+{
15479+ struct au_fidir *fidir;
15480+ int nbr;
15481+
5afbbe0d 15482+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
15483+ if (nbr < 2)
15484+ nbr = 2; /* initial allocate for 2 branches */
15485+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
15486+ if (fidir) {
15487+ fidir->fd_bbot = -1;
15488+ fidir->fd_nent = nbr;
4a4d8108
AM
15489+ }
15490+
15491+ return fidir;
15492+}
15493+
e2f27e51 15494+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink)
4a4d8108
AM
15495+{
15496+ int err;
15497+ struct au_fidir *fidir, *p;
15498+
15499+ AuRwMustWriteLock(&finfo->fi_rwsem);
15500+ fidir = finfo->fi_hdir;
15501+ AuDebugOn(!fidir);
15502+
15503+ err = -ENOMEM;
15504+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
e2f27e51 15505+ GFP_NOFS, may_shrink);
4a4d8108
AM
15506+ if (p) {
15507+ p->fd_nent = nbr;
15508+ finfo->fi_hdir = p;
15509+ err = 0;
15510+ }
1facf9fc 15511+
dece6358 15512+ return err;
1facf9fc 15513+}
1308ab2a 15514+
15515+/* ---------------------------------------------------------------------- */
15516+
1c60b727 15517+void au_finfo_fin(struct file *file)
1308ab2a 15518+{
4a4d8108
AM
15519+ struct au_finfo *finfo;
15520+
acd2b654 15521+ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles);
7f207e10 15522+
4a4d8108
AM
15523+ finfo = au_fi(file);
15524+ AuDebugOn(finfo->fi_hdir);
15525+ AuRwDestroy(&finfo->fi_rwsem);
1c60b727 15526+ au_cache_free_finfo(finfo);
1308ab2a 15527+}
1308ab2a 15528+
e49829fe 15529+void au_fi_init_once(void *_finfo)
4a4d8108 15530+{
e49829fe 15531+ struct au_finfo *finfo = _finfo;
1308ab2a 15532+
e49829fe 15533+ au_rw_init(&finfo->fi_rwsem);
4a4d8108 15534+}
1308ab2a 15535+
4a4d8108
AM
15536+int au_finfo_init(struct file *file, struct au_fidir *fidir)
15537+{
1716fcea 15538+ int err;
4a4d8108
AM
15539+ struct au_finfo *finfo;
15540+ struct dentry *dentry;
15541+
15542+ err = -ENOMEM;
2000de60 15543+ dentry = file->f_path.dentry;
4a4d8108
AM
15544+ finfo = au_cache_alloc_finfo();
15545+ if (unlikely(!finfo))
15546+ goto out;
15547+
15548+ err = 0;
acd2b654 15549+ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles);
4a4d8108
AM
15550+ au_rw_write_lock(&finfo->fi_rwsem);
15551+ finfo->fi_btop = -1;
15552+ finfo->fi_hdir = fidir;
15553+ atomic_set(&finfo->fi_generation, au_digen(dentry));
15554+ /* smp_mb(); */ /* atomic_set */
15555+
15556+ file->private_data = finfo;
15557+
15558+out:
15559+ return err;
15560+}
7f207e10 15561diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
fbc438ed
JR
15562--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 08:00:00.000000000 +0800
15563+++ linux/fs/aufs/f_op.c 2019-07-11 21:21:54.379051070 +0800
acd2b654 15564@@ -0,0 +1,819 @@
cd7a4cd9 15565+// SPDX-License-Identifier: GPL-2.0
dece6358 15566+/*
ba1aed25 15567+ * Copyright (C) 2005-2019 Junjiro R. Okajima
dece6358
AM
15568+ *
15569+ * This program, aufs is free software; you can redistribute it and/or modify
15570+ * it under the terms of the GNU General Public License as published by
15571+ * the Free Software Foundation; either version 2 of the License, or
15572+ * (at your option) any later version.
15573+ *
15574+ * This program is distributed in the hope that it will be useful,
15575+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15576+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15577+ * GNU General Public License for more details.
15578+ *
15579+ * You should have received a copy of the GNU General Public License
523b37e3 15580+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 15581+ */
1facf9fc 15582+
15583+/*
4a4d8108 15584+ * file and vm operations
1facf9fc 15585+ */
dece6358 15586+
86dc4139 15587+#include <linux/aio.h>
4a4d8108
AM
15588+#include <linux/fs_stack.h>
15589+#include <linux/mman.h>
4a4d8108 15590+#include <linux/security.h>
dece6358
AM
15591+#include "aufs.h"
15592+
b912730e 15593+int au_do_open_nondir(struct file *file, int flags, struct file *h_file)
1facf9fc 15594+{
4a4d8108
AM
15595+ int err;
15596+ aufs_bindex_t bindex;
8cdd5066 15597+ struct dentry *dentry, *h_dentry;
4a4d8108 15598+ struct au_finfo *finfo;
38d290e6 15599+ struct inode *h_inode;
4a4d8108
AM
15600+
15601+ FiMustWriteLock(file);
15602+
523b37e3 15603+ err = 0;
2000de60 15604+ dentry = file->f_path.dentry;
b912730e 15605+ AuDebugOn(IS_ERR_OR_NULL(dentry));
4a4d8108
AM
15606+ finfo = au_fi(file);
15607+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 15608+ atomic_set(&finfo->fi_mmapped, 0);
5afbbe0d 15609+ bindex = au_dbtop(dentry);
8cdd5066
JR
15610+ if (!h_file) {
15611+ h_dentry = au_h_dptr(dentry, bindex);
15612+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15613+ if (unlikely(err))
15614+ goto out;
b912730e 15615+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
acd2b654
AM
15616+ if (IS_ERR(h_file)) {
15617+ err = PTR_ERR(h_file);
15618+ goto out;
15619+ }
8cdd5066
JR
15620+ } else {
15621+ h_dentry = h_file->f_path.dentry;
15622+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15623+ if (unlikely(err))
15624+ goto out;
acd2b654 15625+ /* br ref is already inc-ed */
8cdd5066 15626+ }
acd2b654
AM
15627+
15628+ if ((flags & __O_TMPFILE)
15629+ && !(flags & O_EXCL)) {
15630+ h_inode = file_inode(h_file);
15631+ spin_lock(&h_inode->i_lock);
15632+ h_inode->i_state |= I_LINKABLE;
15633+ spin_unlock(&h_inode->i_lock);
4a4d8108 15634+ }
acd2b654
AM
15635+ au_set_fbtop(file, bindex);
15636+ au_set_h_fptr(file, bindex, h_file);
15637+ au_update_figen(file);
15638+ /* todo: necessary? */
15639+ /* file->f_ra = h_file->f_ra; */
027c5e7a 15640+
8cdd5066 15641+out:
4a4d8108 15642+ return err;
1facf9fc 15643+}
15644+
4a4d8108
AM
15645+static int aufs_open_nondir(struct inode *inode __maybe_unused,
15646+ struct file *file)
1facf9fc 15647+{
4a4d8108 15648+ int err;
1308ab2a 15649+ struct super_block *sb;
b912730e
AM
15650+ struct au_do_open_args args = {
15651+ .open = au_do_open_nondir
15652+ };
1facf9fc 15653+
523b37e3
AM
15654+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n",
15655+ file, vfsub_file_flags(file), file->f_mode);
1facf9fc 15656+
2000de60 15657+ sb = file->f_path.dentry->d_sb;
4a4d8108 15658+ si_read_lock(sb, AuLock_FLUSH);
b912730e 15659+ err = au_do_open(file, &args);
4a4d8108
AM
15660+ si_read_unlock(sb);
15661+ return err;
15662+}
1facf9fc 15663+
4a4d8108
AM
15664+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
15665+{
15666+ struct au_finfo *finfo;
15667+ aufs_bindex_t bindex;
1facf9fc 15668+
4a4d8108 15669+ finfo = au_fi(file);
8b6a4947
AM
15670+ au_hbl_del(&finfo->fi_hlist,
15671+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108 15672+ bindex = finfo->fi_btop;
b4510431 15673+ if (bindex >= 0)
4a4d8108 15674+ au_set_h_fptr(file, bindex, NULL);
7f207e10 15675+
1c60b727 15676+ au_finfo_fin(file);
4a4d8108 15677+ return 0;
1facf9fc 15678+}
15679+
4a4d8108
AM
15680+/* ---------------------------------------------------------------------- */
15681+
15682+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 15683+{
1308ab2a 15684+ int err;
4a4d8108
AM
15685+ struct file *h_file;
15686+
15687+ err = 0;
15688+ h_file = au_hf_top(file);
15689+ if (h_file)
15690+ err = vfsub_flush(h_file, id);
15691+ return err;
15692+}
15693+
15694+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
15695+{
15696+ return au_do_flush(file, id, au_do_flush_nondir);
15697+}
15698+
15699+/* ---------------------------------------------------------------------- */
9dbd164d
AM
15700+/*
15701+ * read and write functions acquire [fdi]_rwsem once, but release before
15702+ * mmap_sem. This is because to stop a race condition between mmap(2).
acd2b654 15703+ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping
9dbd164d
AM
15704+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
15705+ * read functions after [fdi]_rwsem are released, but it should be harmless.
15706+ */
4a4d8108 15707+
b912730e 15708+/* Callers should call au_read_post() or fput() in the end */
521ced18 15709+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc)
4a4d8108 15710+{
4a4d8108 15711+ struct file *h_file;
b912730e 15712+ int err;
1facf9fc 15713+
521ced18 15714+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc);
b912730e
AM
15715+ if (!err) {
15716+ di_read_unlock(file->f_path.dentry, AuLock_IR);
15717+ h_file = au_hf_top(file);
15718+ get_file(h_file);
15719+ if (!keep_fi)
15720+ fi_read_unlock(file);
15721+ } else
15722+ h_file = ERR_PTR(err);
15723+
15724+ return h_file;
15725+}
15726+
15727+static void au_read_post(struct inode *inode, struct file *h_file)
15728+{
15729+ /* update without lock, I don't think it a problem */
15730+ fsstack_copy_attr_atime(inode, file_inode(h_file));
15731+ fput(h_file);
15732+}
15733+
15734+struct au_write_pre {
521ced18
JR
15735+ /* input */
15736+ unsigned int lsc;
15737+
15738+ /* output */
b912730e 15739+ blkcnt_t blks;
5afbbe0d 15740+ aufs_bindex_t btop;
b912730e
AM
15741+};
15742+
15743+/*
15744+ * return with iinfo is write-locked
15745+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the
15746+ * end
15747+ */
15748+static struct file *au_write_pre(struct file *file, int do_ready,
15749+ struct au_write_pre *wpre)
15750+{
15751+ struct file *h_file;
15752+ struct dentry *dentry;
15753+ int err;
521ced18 15754+ unsigned int lsc;
b912730e
AM
15755+ struct au_pin pin;
15756+
521ced18
JR
15757+ lsc = 0;
15758+ if (wpre)
15759+ lsc = wpre->lsc;
15760+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc);
b912730e 15761+ h_file = ERR_PTR(err);
dece6358
AM
15762+ if (unlikely(err))
15763+ goto out;
1facf9fc 15764+
b912730e
AM
15765+ dentry = file->f_path.dentry;
15766+ if (do_ready) {
15767+ err = au_ready_to_write(file, -1, &pin);
15768+ if (unlikely(err)) {
15769+ h_file = ERR_PTR(err);
15770+ di_write_unlock(dentry);
15771+ goto out_fi;
15772+ }
15773+ }
15774+
15775+ di_downgrade_lock(dentry, /*flags*/0);
15776+ if (wpre)
5afbbe0d 15777+ wpre->btop = au_fbtop(file);
4a4d8108 15778+ h_file = au_hf_top(file);
9dbd164d 15779+ get_file(h_file);
b912730e
AM
15780+ if (wpre)
15781+ wpre->blks = file_inode(h_file)->i_blocks;
15782+ if (do_ready)
15783+ au_unpin(&pin);
15784+ di_read_unlock(dentry, /*flags*/0);
15785+
15786+out_fi:
15787+ fi_write_unlock(file);
15788+out:
15789+ return h_file;
15790+}
15791+
15792+static void au_write_post(struct inode *inode, struct file *h_file,
15793+ struct au_write_pre *wpre, ssize_t written)
15794+{
15795+ struct inode *h_inode;
15796+
15797+ au_cpup_attr_timesizes(inode);
5afbbe0d 15798+ AuDebugOn(au_ibtop(inode) != wpre->btop);
b912730e
AM
15799+ h_inode = file_inode(h_file);
15800+ inode->i_mode = h_inode->i_mode;
15801+ ii_write_unlock(inode);
b912730e
AM
15802+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */
15803+ if (written > 0)
5afbbe0d 15804+ au_fhsm_wrote(inode->i_sb, wpre->btop,
b912730e 15805+ /*force*/h_inode->i_blocks > wpre->blks);
1c60b727 15806+ fput(h_file);
b912730e
AM
15807+}
15808+
15809+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
15810+ loff_t *ppos)
15811+{
15812+ ssize_t err;
15813+ struct inode *inode;
15814+ struct file *h_file;
15815+ struct super_block *sb;
15816+
15817+ inode = file_inode(file);
15818+ sb = inode->i_sb;
15819+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
15820+
521ced18 15821+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
15822+ err = PTR_ERR(h_file);
15823+ if (IS_ERR(h_file))
15824+ goto out;
9dbd164d
AM
15825+
15826+ /* filedata may be obsoleted by concurrent copyup, but no problem */
4a4d8108
AM
15827+ err = vfsub_read_u(h_file, buf, count, ppos);
15828+ /* todo: necessary? */
15829+ /* file->f_ra = h_file->f_ra; */
b912730e 15830+ au_read_post(inode, h_file);
1308ab2a 15831+
4f0767ce 15832+out:
dece6358
AM
15833+ si_read_unlock(sb);
15834+ return err;
15835+}
1facf9fc 15836+
e49829fe
JR
15837+/*
15838+ * todo: very ugly
15839+ * it locks both of i_mutex and si_rwsem for read in safe.
15840+ * if the plink maintenance mode continues forever (that is the problem),
15841+ * may loop forever.
15842+ */
15843+static void au_mtx_and_read_lock(struct inode *inode)
15844+{
15845+ int err;
15846+ struct super_block *sb = inode->i_sb;
15847+
15848+ while (1) {
febd17d6 15849+ inode_lock(inode);
e49829fe
JR
15850+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15851+ if (!err)
15852+ break;
febd17d6 15853+ inode_unlock(inode);
e49829fe
JR
15854+ si_read_lock(sb, AuLock_NOPLMW);
15855+ si_read_unlock(sb);
15856+ }
15857+}
15858+
4a4d8108
AM
15859+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
15860+ size_t count, loff_t *ppos)
dece6358 15861+{
4a4d8108 15862+ ssize_t err;
b912730e
AM
15863+ struct au_write_pre wpre;
15864+ struct inode *inode;
4a4d8108
AM
15865+ struct file *h_file;
15866+ char __user *buf = (char __user *)ubuf;
1facf9fc 15867+
b912730e 15868+ inode = file_inode(file);
e49829fe 15869+ au_mtx_and_read_lock(inode);
1facf9fc 15870+
521ced18 15871+ wpre.lsc = 0;
b912730e
AM
15872+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15873+ err = PTR_ERR(h_file);
15874+ if (IS_ERR(h_file))
9dbd164d 15875+ goto out;
9dbd164d 15876+
4a4d8108 15877+ err = vfsub_write_u(h_file, buf, count, ppos);
b912730e 15878+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15879+
4f0767ce 15880+out:
b912730e 15881+ si_read_unlock(inode->i_sb);
febd17d6 15882+ inode_unlock(inode);
dece6358
AM
15883+ return err;
15884+}
1facf9fc 15885+
076b876e
AM
15886+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio,
15887+ struct iov_iter *iov_iter)
dece6358 15888+{
4a4d8108
AM
15889+ ssize_t err;
15890+ struct file *file;
076b876e 15891+ ssize_t (*iter)(struct kiocb *, struct iov_iter *);
1facf9fc 15892+
4a4d8108
AM
15893+ err = security_file_permission(h_file, rw);
15894+ if (unlikely(err))
15895+ goto out;
1facf9fc 15896+
4a4d8108 15897+ err = -ENOSYS;
076b876e 15898+ iter = NULL;
5527c038 15899+ if (rw == MAY_READ)
076b876e 15900+ iter = h_file->f_op->read_iter;
5527c038 15901+ else if (rw == MAY_WRITE)
076b876e 15902+ iter = h_file->f_op->write_iter;
076b876e
AM
15903+
15904+ file = kio->ki_filp;
15905+ kio->ki_filp = h_file;
15906+ if (iter) {
2cbb1c4b 15907+ lockdep_off();
076b876e
AM
15908+ err = iter(kio, iov_iter);
15909+ lockdep_on();
4a4d8108
AM
15910+ } else
15911+ /* currently there is no such fs */
15912+ WARN_ON_ONCE(1);
076b876e 15913+ kio->ki_filp = file;
1facf9fc 15914+
4f0767ce 15915+out:
dece6358
AM
15916+ return err;
15917+}
1facf9fc 15918+
076b876e 15919+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1facf9fc 15920+{
4a4d8108
AM
15921+ ssize_t err;
15922+ struct file *file, *h_file;
b912730e 15923+ struct inode *inode;
dece6358 15924+ struct super_block *sb;
1facf9fc 15925+
4a4d8108 15926+ file = kio->ki_filp;
b912730e
AM
15927+ inode = file_inode(file);
15928+ sb = inode->i_sb;
e49829fe 15929+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 15930+
521ced18 15931+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0);
b912730e
AM
15932+ err = PTR_ERR(h_file);
15933+ if (IS_ERR(h_file))
15934+ goto out;
9dbd164d 15935+
5afbbe0d
AM
15936+ if (au_test_loopback_kthread()) {
15937+ au_warn_loopback(h_file->f_path.dentry->d_sb);
15938+ if (file->f_mapping != h_file->f_mapping) {
15939+ file->f_mapping = h_file->f_mapping;
15940+ smp_mb(); /* unnecessary? */
15941+ }
15942+ }
15943+ fi_read_unlock(file);
15944+
076b876e 15945+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter);
4a4d8108
AM
15946+ /* todo: necessary? */
15947+ /* file->f_ra = h_file->f_ra; */
b912730e 15948+ au_read_post(inode, h_file);
1facf9fc 15949+
4f0767ce 15950+out:
4a4d8108 15951+ si_read_unlock(sb);
1308ab2a 15952+ return err;
15953+}
1facf9fc 15954+
076b876e 15955+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1308ab2a 15956+{
4a4d8108 15957+ ssize_t err;
b912730e
AM
15958+ struct au_write_pre wpre;
15959+ struct inode *inode;
4a4d8108 15960+ struct file *file, *h_file;
1308ab2a 15961+
4a4d8108 15962+ file = kio->ki_filp;
b912730e 15963+ inode = file_inode(file);
e49829fe
JR
15964+ au_mtx_and_read_lock(inode);
15965+
521ced18 15966+ wpre.lsc = 0;
b912730e
AM
15967+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15968+ err = PTR_ERR(h_file);
15969+ if (IS_ERR(h_file))
9dbd164d 15970+ goto out;
9dbd164d 15971+
076b876e 15972+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter);
b912730e 15973+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15974+
4f0767ce 15975+out:
b912730e 15976+ si_read_unlock(inode->i_sb);
febd17d6 15977+ inode_unlock(inode);
dece6358 15978+ return err;
1facf9fc 15979+}
15980+
4a4d8108
AM
15981+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
15982+ struct pipe_inode_info *pipe, size_t len,
15983+ unsigned int flags)
1facf9fc 15984+{
4a4d8108
AM
15985+ ssize_t err;
15986+ struct file *h_file;
b912730e 15987+ struct inode *inode;
dece6358 15988+ struct super_block *sb;
1facf9fc 15989+
b912730e
AM
15990+ inode = file_inode(file);
15991+ sb = inode->i_sb;
e49829fe 15992+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 15993+
521ced18 15994+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
15995+ err = PTR_ERR(h_file);
15996+ if (IS_ERR(h_file))
dece6358 15997+ goto out;
1facf9fc 15998+
4a4d8108 15999+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
acd2b654 16000+ /* todo: necessary? */
4a4d8108 16001+ /* file->f_ra = h_file->f_ra; */
b912730e 16002+ au_read_post(inode, h_file);
1facf9fc 16003+
4f0767ce 16004+out:
4a4d8108 16005+ si_read_unlock(sb);
dece6358 16006+ return err;
1facf9fc 16007+}
16008+
4a4d8108
AM
16009+static ssize_t
16010+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
16011+ size_t len, unsigned int flags)
1facf9fc 16012+{
4a4d8108 16013+ ssize_t err;
b912730e
AM
16014+ struct au_write_pre wpre;
16015+ struct inode *inode;
076b876e 16016+ struct file *h_file;
1facf9fc 16017+
b912730e 16018+ inode = file_inode(file);
e49829fe 16019+ au_mtx_and_read_lock(inode);
9dbd164d 16020+
521ced18 16021+ wpre.lsc = 0;
b912730e
AM
16022+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16023+ err = PTR_ERR(h_file);
16024+ if (IS_ERR(h_file))
9dbd164d 16025+ goto out;
9dbd164d 16026+
4a4d8108 16027+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
b912730e 16028+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 16029+
4f0767ce 16030+out:
b912730e 16031+ si_read_unlock(inode->i_sb);
febd17d6 16032+ inode_unlock(inode);
4a4d8108
AM
16033+ return err;
16034+}
1facf9fc 16035+
38d290e6
JR
16036+static long aufs_fallocate(struct file *file, int mode, loff_t offset,
16037+ loff_t len)
16038+{
16039+ long err;
b912730e 16040+ struct au_write_pre wpre;
38d290e6
JR
16041+ struct inode *inode;
16042+ struct file *h_file;
16043+
b912730e 16044+ inode = file_inode(file);
38d290e6
JR
16045+ au_mtx_and_read_lock(inode);
16046+
521ced18 16047+ wpre.lsc = 0;
b912730e
AM
16048+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16049+ err = PTR_ERR(h_file);
16050+ if (IS_ERR(h_file))
38d290e6 16051+ goto out;
38d290e6
JR
16052+
16053+ lockdep_off();
03673fb0 16054+ err = vfs_fallocate(h_file, mode, offset, len);
38d290e6 16055+ lockdep_on();
b912730e 16056+ au_write_post(inode, h_file, &wpre, /*written*/1);
38d290e6
JR
16057+
16058+out:
b912730e 16059+ si_read_unlock(inode->i_sb);
febd17d6 16060+ inode_unlock(inode);
38d290e6
JR
16061+ return err;
16062+}
16063+
521ced18
JR
16064+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos,
16065+ struct file *dst, loff_t dst_pos,
16066+ size_t len, unsigned int flags)
16067+{
16068+ ssize_t err;
16069+ struct au_write_pre wpre;
16070+ enum { SRC, DST };
16071+ struct {
16072+ struct inode *inode;
16073+ struct file *h_file;
16074+ struct super_block *h_sb;
16075+ } a[2];
16076+#define a_src a[SRC]
16077+#define a_dst a[DST]
16078+
16079+ err = -EINVAL;
16080+ a_src.inode = file_inode(src);
16081+ if (unlikely(!S_ISREG(a_src.inode->i_mode)))
16082+ goto out;
16083+ a_dst.inode = file_inode(dst);
16084+ if (unlikely(!S_ISREG(a_dst.inode->i_mode)))
16085+ goto out;
16086+
16087+ au_mtx_and_read_lock(a_dst.inode);
16088+ /*
16089+ * in order to match the order in di_write_lock2_{child,parent}(),
acd2b654 16090+ * use f_path.dentry for this comparison.
521ced18
JR
16091+ */
16092+ if (src->f_path.dentry < dst->f_path.dentry) {
16093+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1);
16094+ err = PTR_ERR(a_src.h_file);
16095+ if (IS_ERR(a_src.h_file))
16096+ goto out_si;
16097+
16098+ wpre.lsc = AuLsc_FI_2;
16099+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
16100+ err = PTR_ERR(a_dst.h_file);
16101+ if (IS_ERR(a_dst.h_file)) {
16102+ au_read_post(a_src.inode, a_src.h_file);
16103+ goto out_si;
16104+ }
16105+ } else {
16106+ wpre.lsc = AuLsc_FI_1;
16107+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
16108+ err = PTR_ERR(a_dst.h_file);
16109+ if (IS_ERR(a_dst.h_file))
16110+ goto out_si;
16111+
16112+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2);
16113+ err = PTR_ERR(a_src.h_file);
16114+ if (IS_ERR(a_src.h_file)) {
16115+ au_write_post(a_dst.inode, a_dst.h_file, &wpre,
16116+ /*written*/0);
16117+ goto out_si;
16118+ }
16119+ }
16120+
16121+ err = -EXDEV;
16122+ a_src.h_sb = file_inode(a_src.h_file)->i_sb;
16123+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb;
16124+ if (unlikely(a_src.h_sb != a_dst.h_sb)) {
16125+ AuDbgFile(src);
16126+ AuDbgFile(dst);
16127+ goto out_file;
16128+ }
16129+
16130+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file,
16131+ dst_pos, len, flags);
16132+
16133+out_file:
16134+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err);
16135+ fi_read_unlock(src);
16136+ au_read_post(a_src.inode, a_src.h_file);
16137+out_si:
16138+ si_read_unlock(a_dst.inode->i_sb);
16139+ inode_unlock(a_dst.inode);
16140+out:
16141+ return err;
16142+#undef a_src
16143+#undef a_dst
16144+}
16145+
4a4d8108
AM
16146+/* ---------------------------------------------------------------------- */
16147+
9dbd164d
AM
16148+/*
16149+ * The locking order around current->mmap_sem.
16150+ * - in most and regular cases
16151+ * file I/O syscall -- aufs_read() or something
16152+ * -- si_rwsem for read -- mmap_sem
16153+ * (Note that [fdi]i_rwsem are released before mmap_sem).
16154+ * - in mmap case
16155+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
acd2b654
AM
16156+ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for
16157+ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held
16158+ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
9dbd164d
AM
16159+ * It means that when aufs acquires si_rwsem for write, the process should never
16160+ * acquire mmap_sem.
16161+ *
392086de 16162+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a
9dbd164d
AM
16163+ * problem either since any directory is not able to be mmap-ed.
16164+ * The similar scenario is applied to aufs_readlink() too.
16165+ */
16166+
38d290e6 16167+#if 0 /* stop calling security_file_mmap() */
2dfbb274
AM
16168+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
16169+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
16170+
16171+static unsigned long au_arch_prot_conv(unsigned long flags)
16172+{
16173+ /* currently ppc64 only */
16174+#ifdef CONFIG_PPC64
16175+ /* cf. linux/arch/powerpc/include/asm/mman.h */
16176+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
16177+ return AuConv_VM_PROT(flags, SAO);
16178+#else
16179+ AuDebugOn(arch_calc_vm_prot_bits(-1));
16180+ return 0;
16181+#endif
16182+}
16183+
16184+static unsigned long au_prot_conv(unsigned long flags)
16185+{
16186+ return AuConv_VM_PROT(flags, READ)
16187+ | AuConv_VM_PROT(flags, WRITE)
16188+ | AuConv_VM_PROT(flags, EXEC)
16189+ | au_arch_prot_conv(flags);
16190+}
16191+
16192+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
16193+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
16194+
16195+static unsigned long au_flag_conv(unsigned long flags)
16196+{
16197+ return AuConv_VM_MAP(flags, GROWSDOWN)
16198+ | AuConv_VM_MAP(flags, DENYWRITE)
2dfbb274
AM
16199+ | AuConv_VM_MAP(flags, LOCKED);
16200+}
38d290e6 16201+#endif
2dfbb274 16202+
9dbd164d 16203+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 16204+{
4a4d8108 16205+ int err;
4a4d8108 16206+ const unsigned char wlock
9dbd164d 16207+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108 16208+ struct super_block *sb;
9dbd164d 16209+ struct file *h_file;
b912730e 16210+ struct inode *inode;
9dbd164d
AM
16211+
16212+ AuDbgVmRegion(file, vma);
1308ab2a 16213+
b912730e
AM
16214+ inode = file_inode(file);
16215+ sb = inode->i_sb;
9dbd164d 16216+ lockdep_off();
e49829fe 16217+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108 16218+
b912730e 16219+ h_file = au_write_pre(file, wlock, /*wpre*/NULL);
9dbd164d 16220+ lockdep_on();
b912730e
AM
16221+ err = PTR_ERR(h_file);
16222+ if (IS_ERR(h_file))
16223+ goto out;
1308ab2a 16224+
b912730e
AM
16225+ err = 0;
16226+ au_set_mmapped(file);
9dbd164d 16227+ au_vm_file_reset(vma, h_file);
38d290e6
JR
16228+ /*
16229+ * we cannot call security_mmap_file() here since it may acquire
16230+ * mmap_sem or i_mutex.
16231+ *
16232+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags),
16233+ * au_flag_conv(vma->vm_flags));
16234+ */
9dbd164d 16235+ if (!err)
521ced18 16236+ err = call_mmap(h_file, vma);
b912730e
AM
16237+ if (!err) {
16238+ au_vm_prfile_set(vma, file);
16239+ fsstack_copy_attr_atime(inode, file_inode(h_file));
16240+ goto out_fput; /* success */
16241+ }
2cbb1c4b
JR
16242+ au_unset_mmapped(file);
16243+ au_vm_file_reset(vma, file);
b912730e 16244+
2cbb1c4b 16245+out_fput:
9dbd164d 16246+ lockdep_off();
b912730e
AM
16247+ ii_write_unlock(inode);
16248+ lockdep_on();
16249+ fput(h_file);
4f0767ce 16250+out:
b912730e 16251+ lockdep_off();
9dbd164d
AM
16252+ si_read_unlock(sb);
16253+ lockdep_on();
16254+ AuTraceErr(err);
4a4d8108
AM
16255+ return err;
16256+}
16257+
16258+/* ---------------------------------------------------------------------- */
16259+
1e00d052
AM
16260+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
16261+ int datasync)
4a4d8108
AM
16262+{
16263+ int err;
b912730e 16264+ struct au_write_pre wpre;
4a4d8108
AM
16265+ struct inode *inode;
16266+ struct file *h_file;
4a4d8108
AM
16267+
16268+ err = 0; /* -EBADF; */ /* posix? */
16269+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
b912730e 16270+ goto out;
4a4d8108 16271+
b912730e
AM
16272+ inode = file_inode(file);
16273+ au_mtx_and_read_lock(inode);
16274+
521ced18 16275+ wpre.lsc = 0;
b912730e
AM
16276+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16277+ err = PTR_ERR(h_file);
16278+ if (IS_ERR(h_file))
4a4d8108 16279+ goto out_unlock;
4a4d8108 16280+
53392da6 16281+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
b912730e 16282+ au_write_post(inode, h_file, &wpre, /*written*/0);
4a4d8108 16283+
4f0767ce 16284+out_unlock:
b912730e 16285+ si_read_unlock(inode->i_sb);
febd17d6 16286+ inode_unlock(inode);
b912730e 16287+out:
4a4d8108 16288+ return err;
dece6358
AM
16289+}
16290+
4a4d8108 16291+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 16292+{
4a4d8108
AM
16293+ int err;
16294+ struct file *h_file;
4a4d8108 16295+ struct super_block *sb;
1308ab2a 16296+
b912730e 16297+ sb = file->f_path.dentry->d_sb;
e49829fe 16298+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 16299+
521ced18 16300+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
16301+ err = PTR_ERR(h_file);
16302+ if (IS_ERR(h_file))
4a4d8108
AM
16303+ goto out;
16304+
523b37e3 16305+ if (h_file->f_op->fasync)
4a4d8108 16306+ err = h_file->f_op->fasync(fd, h_file, flag);
b912730e 16307+ fput(h_file); /* instead of au_read_post() */
1308ab2a 16308+
4f0767ce 16309+out:
4a4d8108 16310+ si_read_unlock(sb);
1308ab2a 16311+ return err;
dece6358 16312+}
4a4d8108 16313+
febd17d6
JR
16314+static int aufs_setfl(struct file *file, unsigned long arg)
16315+{
16316+ int err;
16317+ struct file *h_file;
16318+ struct super_block *sb;
16319+
16320+ sb = file->f_path.dentry->d_sb;
16321+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
16322+
521ced18 16323+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
febd17d6
JR
16324+ err = PTR_ERR(h_file);
16325+ if (IS_ERR(h_file))
16326+ goto out;
16327+
1c60b727
AM
16328+ /* stop calling h_file->fasync */
16329+ arg |= vfsub_file_flags(file) & FASYNC;
febd17d6
JR
16330+ err = setfl(/*unused fd*/-1, h_file, arg);
16331+ fput(h_file); /* instead of au_read_post() */
16332+
16333+out:
16334+ si_read_unlock(sb);
16335+ return err;
16336+}
16337+
4a4d8108
AM
16338+/* ---------------------------------------------------------------------- */
16339+
16340+/* no one supports this operation, currently */
16341+#if 0
16342+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
2000de60 16343+ size_t len, loff_t *pos, int more)
4a4d8108
AM
16344+{
16345+}
16346+#endif
16347+
16348+/* ---------------------------------------------------------------------- */
16349+
16350+const struct file_operations aufs_file_fop = {
16351+ .owner = THIS_MODULE,
2cbb1c4b 16352+
027c5e7a 16353+ .llseek = default_llseek,
4a4d8108
AM
16354+
16355+ .read = aufs_read,
16356+ .write = aufs_write,
076b876e
AM
16357+ .read_iter = aufs_read_iter,
16358+ .write_iter = aufs_write_iter,
16359+
4a4d8108
AM
16360+#ifdef CONFIG_AUFS_POLL
16361+ .poll = aufs_poll,
16362+#endif
16363+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1 16364+#ifdef CONFIG_COMPAT
c2b27bf2 16365+ .compat_ioctl = aufs_compat_ioctl_nondir,
b752ccd1 16366+#endif
4a4d8108
AM
16367+ .mmap = aufs_mmap,
16368+ .open = aufs_open_nondir,
16369+ .flush = aufs_flush_nondir,
16370+ .release = aufs_release_nondir,
16371+ .fsync = aufs_fsync_nondir,
4a4d8108
AM
16372+ .fasync = aufs_fasync,
16373+ /* .sendpage = aufs_sendpage, */
febd17d6 16374+ .setfl = aufs_setfl,
4a4d8108
AM
16375+ .splice_write = aufs_splice_write,
16376+ .splice_read = aufs_splice_read,
16377+#if 0
16378+ .aio_splice_write = aufs_aio_splice_write,
38d290e6 16379+ .aio_splice_read = aufs_aio_splice_read,
4a4d8108 16380+#endif
521ced18
JR
16381+ .fallocate = aufs_fallocate,
16382+ .copy_file_range = aufs_copy_file_range
4a4d8108 16383+};
7f207e10 16384diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
fbc438ed
JR
16385--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 08:00:00.000000000 +0800
16386+++ linux/fs/aufs/fstype.h 2019-07-11 21:21:54.379051070 +0800
062440b3
AM
16387@@ -0,0 +1,401 @@
16388+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 16389+/*
ba1aed25 16390+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
16391+ *
16392+ * This program, aufs is free software; you can redistribute it and/or modify
16393+ * it under the terms of the GNU General Public License as published by
16394+ * the Free Software Foundation; either version 2 of the License, or
16395+ * (at your option) any later version.
16396+ *
16397+ * This program is distributed in the hope that it will be useful,
16398+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16399+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16400+ * GNU General Public License for more details.
16401+ *
16402+ * You should have received a copy of the GNU General Public License
523b37e3 16403+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
16404+ */
16405+
16406+/*
16407+ * judging filesystem type
16408+ */
16409+
16410+#ifndef __AUFS_FSTYPE_H__
16411+#define __AUFS_FSTYPE_H__
16412+
16413+#ifdef __KERNEL__
16414+
16415+#include <linux/fs.h>
16416+#include <linux/magic.h>
b912730e 16417+#include <linux/nfs_fs.h>
b95c5147 16418+#include <linux/romfs_fs.h>
4a4d8108
AM
16419+
16420+static inline int au_test_aufs(struct super_block *sb)
16421+{
16422+ return sb->s_magic == AUFS_SUPER_MAGIC;
16423+}
16424+
16425+static inline const char *au_sbtype(struct super_block *sb)
16426+{
16427+ return sb->s_type->name;
16428+}
1308ab2a 16429+
16430+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
16431+{
f0c0a007 16432+#if IS_ENABLED(CONFIG_ISO9660_FS)
2000de60 16433+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
16434+#else
16435+ return 0;
16436+#endif
16437+}
16438+
1308ab2a 16439+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 16440+{
f0c0a007 16441+#if IS_ENABLED(CONFIG_ROMFS_FS)
2000de60 16442+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
16443+#else
16444+ return 0;
16445+#endif
16446+}
16447+
1308ab2a 16448+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 16449+{
f0c0a007 16450+#if IS_ENABLED(CONFIG_CRAMFS)
1308ab2a 16451+ return sb->s_magic == CRAMFS_MAGIC;
16452+#endif
16453+ return 0;
16454+}
16455+
16456+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
16457+{
f0c0a007 16458+#if IS_ENABLED(CONFIG_NFS_FS)
1308ab2a 16459+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
16460+#else
16461+ return 0;
16462+#endif
16463+}
16464+
1308ab2a 16465+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 16466+{
f0c0a007 16467+#if IS_ENABLED(CONFIG_FUSE_FS)
1308ab2a 16468+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
16469+#else
16470+ return 0;
16471+#endif
16472+}
16473+
1308ab2a 16474+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 16475+{
f0c0a007 16476+#if IS_ENABLED(CONFIG_XFS_FS)
1308ab2a 16477+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
16478+#else
16479+ return 0;
16480+#endif
16481+}
16482+
1308ab2a 16483+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 16484+{
1308ab2a 16485+#ifdef CONFIG_TMPFS
16486+ return sb->s_magic == TMPFS_MAGIC;
16487+#else
16488+ return 0;
dece6358 16489+#endif
dece6358
AM
16490+}
16491+
1308ab2a 16492+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 16493+{
f0c0a007 16494+#if IS_ENABLED(CONFIG_ECRYPT_FS)
1308ab2a 16495+ return !strcmp(au_sbtype(sb), "ecryptfs");
16496+#else
16497+ return 0;
16498+#endif
1facf9fc 16499+}
16500+
1308ab2a 16501+static inline int au_test_ramfs(struct super_block *sb)
16502+{
16503+ return sb->s_magic == RAMFS_MAGIC;
16504+}
16505+
16506+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
16507+{
f0c0a007 16508+#if IS_ENABLED(CONFIG_UBIFS_FS)
1308ab2a 16509+ return sb->s_magic == UBIFS_SUPER_MAGIC;
16510+#else
16511+ return 0;
16512+#endif
16513+}
16514+
16515+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
16516+{
16517+#ifdef CONFIG_PROC_FS
16518+ return sb->s_magic == PROC_SUPER_MAGIC;
16519+#else
16520+ return 0;
16521+#endif
16522+}
16523+
16524+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
16525+{
16526+#ifdef CONFIG_SYSFS
16527+ return sb->s_magic == SYSFS_MAGIC;
16528+#else
16529+ return 0;
16530+#endif
16531+}
16532+
16533+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
16534+{
f0c0a007 16535+#if IS_ENABLED(CONFIG_CONFIGFS_FS)
1308ab2a 16536+ return sb->s_magic == CONFIGFS_MAGIC;
16537+#else
16538+ return 0;
16539+#endif
16540+}
16541+
16542+static inline int au_test_minix(struct super_block *sb __maybe_unused)
16543+{
f0c0a007 16544+#if IS_ENABLED(CONFIG_MINIX_FS)
1308ab2a 16545+ return sb->s_magic == MINIX3_SUPER_MAGIC
16546+ || sb->s_magic == MINIX2_SUPER_MAGIC
16547+ || sb->s_magic == MINIX2_SUPER_MAGIC2
16548+ || sb->s_magic == MINIX_SUPER_MAGIC
16549+ || sb->s_magic == MINIX_SUPER_MAGIC2;
16550+#else
16551+ return 0;
16552+#endif
16553+}
16554+
1308ab2a 16555+static inline int au_test_fat(struct super_block *sb __maybe_unused)
16556+{
f0c0a007 16557+#if IS_ENABLED(CONFIG_FAT_FS)
1308ab2a 16558+ return sb->s_magic == MSDOS_SUPER_MAGIC;
16559+#else
16560+ return 0;
16561+#endif
16562+}
16563+
16564+static inline int au_test_msdos(struct super_block *sb)
16565+{
16566+ return au_test_fat(sb);
16567+}
16568+
16569+static inline int au_test_vfat(struct super_block *sb)
16570+{
16571+ return au_test_fat(sb);
16572+}
16573+
16574+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
16575+{
16576+#ifdef CONFIG_SECURITYFS
16577+ return sb->s_magic == SECURITYFS_MAGIC;
16578+#else
16579+ return 0;
16580+#endif
16581+}
16582+
16583+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
16584+{
f0c0a007 16585+#if IS_ENABLED(CONFIG_SQUASHFS)
1308ab2a 16586+ return sb->s_magic == SQUASHFS_MAGIC;
16587+#else
16588+ return 0;
16589+#endif
16590+}
16591+
16592+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
16593+{
f0c0a007 16594+#if IS_ENABLED(CONFIG_BTRFS_FS)
1308ab2a 16595+ return sb->s_magic == BTRFS_SUPER_MAGIC;
16596+#else
16597+ return 0;
16598+#endif
16599+}
16600+
16601+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
16602+{
f0c0a007 16603+#if IS_ENABLED(CONFIG_XENFS)
1308ab2a 16604+ return sb->s_magic == XENFS_SUPER_MAGIC;
16605+#else
16606+ return 0;
16607+#endif
16608+}
16609+
16610+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
16611+{
16612+#ifdef CONFIG_DEBUG_FS
16613+ return sb->s_magic == DEBUGFS_MAGIC;
16614+#else
16615+ return 0;
16616+#endif
16617+}
16618+
16619+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
16620+{
f0c0a007 16621+#if IS_ENABLED(CONFIG_NILFS)
1308ab2a 16622+ return sb->s_magic == NILFS_SUPER_MAGIC;
16623+#else
16624+ return 0;
16625+#endif
16626+}
16627+
4a4d8108
AM
16628+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
16629+{
f0c0a007 16630+#if IS_ENABLED(CONFIG_HFSPLUS_FS)
4a4d8108
AM
16631+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
16632+#else
16633+ return 0;
16634+#endif
16635+}
16636+
1308ab2a 16637+/* ---------------------------------------------------------------------- */
16638+/*
16639+ * they can't be an aufs branch.
16640+ */
16641+static inline int au_test_fs_unsuppoted(struct super_block *sb)
16642+{
16643+ return
16644+#ifndef CONFIG_AUFS_BR_RAMFS
16645+ au_test_ramfs(sb) ||
16646+#endif
16647+ au_test_procfs(sb)
16648+ || au_test_sysfs(sb)
16649+ || au_test_configfs(sb)
16650+ || au_test_debugfs(sb)
16651+ || au_test_securityfs(sb)
16652+ || au_test_xenfs(sb)
16653+ || au_test_ecryptfs(sb)
16654+ /* || !strcmp(au_sbtype(sb), "unionfs") */
16655+ || au_test_aufs(sb); /* will be supported in next version */
16656+}
16657+
1308ab2a 16658+static inline int au_test_fs_remote(struct super_block *sb)
16659+{
16660+ return !au_test_tmpfs(sb)
16661+#ifdef CONFIG_AUFS_BR_RAMFS
16662+ && !au_test_ramfs(sb)
16663+#endif
16664+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
16665+}
16666+
16667+/* ---------------------------------------------------------------------- */
16668+
16669+/*
16670+ * Note: these functions (below) are created after reading ->getattr() in all
16671+ * filesystems under linux/fs. it means we have to do so in every update...
16672+ */
16673+
16674+/*
16675+ * some filesystems require getattr to refresh the inode attributes before
16676+ * referencing.
16677+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
16678+ * and leave the work for d_revalidate()
16679+ */
16680+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
16681+{
16682+ return au_test_nfs(sb)
16683+ || au_test_fuse(sb)
1308ab2a 16684+ /* || au_test_btrfs(sb) */ /* untested */
1308ab2a 16685+ ;
16686+}
16687+
16688+/*
16689+ * filesystems which don't maintain i_size or i_blocks.
16690+ */
16691+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
16692+{
16693+ return au_test_xfs(sb)
4a4d8108
AM
16694+ || au_test_btrfs(sb)
16695+ || au_test_ubifs(sb)
16696+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 16697+ /* || au_test_minix(sb) */ /* untested */
16698+ ;
16699+}
16700+
16701+/*
16702+ * filesystems which don't store the correct value in some of their inode
16703+ * attributes.
16704+ */
16705+static inline int au_test_fs_bad_iattr(struct super_block *sb)
16706+{
16707+ return au_test_fs_bad_iattr_size(sb)
1308ab2a 16708+ || au_test_fat(sb)
16709+ || au_test_msdos(sb)
16710+ || au_test_vfat(sb);
1facf9fc 16711+}
16712+
16713+/* they don't check i_nlink in link(2) */
16714+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
16715+{
16716+ return au_test_tmpfs(sb)
16717+#ifdef CONFIG_AUFS_BR_RAMFS
16718+ || au_test_ramfs(sb)
16719+#endif
4a4d8108 16720+ || au_test_ubifs(sb)
4a4d8108 16721+ || au_test_hfsplus(sb);
1facf9fc 16722+}
16723+
16724+/*
16725+ * filesystems which sets S_NOATIME and S_NOCMTIME.
16726+ */
16727+static inline int au_test_fs_notime(struct super_block *sb)
16728+{
16729+ return au_test_nfs(sb)
16730+ || au_test_fuse(sb)
dece6358 16731+ || au_test_ubifs(sb)
1facf9fc 16732+ ;
16733+}
16734+
1facf9fc 16735+/* temporary support for i#1 in cramfs */
16736+static inline int au_test_fs_unique_ino(struct inode *inode)
16737+{
16738+ if (au_test_cramfs(inode->i_sb))
16739+ return inode->i_ino != 1;
16740+ return 1;
16741+}
16742+
16743+/* ---------------------------------------------------------------------- */
16744+
16745+/*
16746+ * the filesystem where the xino files placed must support i/o after unlink and
16747+ * maintain i_size and i_blocks.
16748+ */
16749+static inline int au_test_fs_bad_xino(struct super_block *sb)
16750+{
16751+ return au_test_fs_remote(sb)
16752+ || au_test_fs_bad_iattr_size(sb)
1facf9fc 16753+ /* don't want unnecessary work for xino */
16754+ || au_test_aufs(sb)
1308ab2a 16755+ || au_test_ecryptfs(sb)
16756+ || au_test_nilfs(sb);
1facf9fc 16757+}
16758+
16759+static inline int au_test_fs_trunc_xino(struct super_block *sb)
16760+{
16761+ return au_test_tmpfs(sb)
16762+ || au_test_ramfs(sb);
16763+}
16764+
16765+/*
16766+ * test if the @sb is real-readonly.
16767+ */
16768+static inline int au_test_fs_rr(struct super_block *sb)
16769+{
16770+ return au_test_squashfs(sb)
16771+ || au_test_iso9660(sb)
16772+ || au_test_cramfs(sb)
16773+ || au_test_romfs(sb);
16774+}
16775+
b912730e
AM
16776+/*
16777+ * test if the @inode is nfs with 'noacl' option
2121bcd9 16778+ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e
AM
16779+ */
16780+static inline int au_test_nfs_noacl(struct inode *inode)
16781+{
16782+ return au_test_nfs(inode->i_sb)
16783+ /* && IS_POSIXACL(inode) */
16784+ && !nfs_server_capable(inode, NFS_CAP_ACLS);
16785+}
16786+
1facf9fc 16787+#endif /* __KERNEL__ */
16788+#endif /* __AUFS_FSTYPE_H__ */
8b6a4947 16789diff -urN /usr/share/empty/fs/aufs/hbl.h linux/fs/aufs/hbl.h
fbc438ed
JR
16790--- /usr/share/empty/fs/aufs/hbl.h 1970-01-01 08:00:00.000000000 +0800
16791+++ linux/fs/aufs/hbl.h 2019-07-11 21:21:54.379051070 +0800
062440b3
AM
16792@@ -0,0 +1,65 @@
16793+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 16794+/*
ba1aed25 16795+ * Copyright (C) 2017-2019 Junjiro R. Okajima
8b6a4947
AM
16796+ *
16797+ * This program, aufs is free software; you can redistribute it and/or modify
16798+ * it under the terms of the GNU General Public License as published by
16799+ * the Free Software Foundation; either version 2 of the License, or
16800+ * (at your option) any later version.
16801+ *
16802+ * This program is distributed in the hope that it will be useful,
16803+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16804+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16805+ * GNU General Public License for more details.
16806+ *
16807+ * You should have received a copy of the GNU General Public License
16808+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16809+ */
16810+
16811+/*
16812+ * helpers for hlist_bl.h
16813+ */
16814+
16815+#ifndef __AUFS_HBL_H__
16816+#define __AUFS_HBL_H__
16817+
16818+#ifdef __KERNEL__
16819+
16820+#include <linux/list_bl.h>
16821+
16822+static inline void au_hbl_add(struct hlist_bl_node *node,
16823+ struct hlist_bl_head *hbl)
16824+{
16825+ hlist_bl_lock(hbl);
16826+ hlist_bl_add_head(node, hbl);
16827+ hlist_bl_unlock(hbl);
16828+}
16829+
16830+static inline void au_hbl_del(struct hlist_bl_node *node,
16831+ struct hlist_bl_head *hbl)
16832+{
16833+ hlist_bl_lock(hbl);
16834+ hlist_bl_del(node);
16835+ hlist_bl_unlock(hbl);
16836+}
16837+
16838+#define au_hbl_for_each(pos, head) \
16839+ for (pos = hlist_bl_first(head); \
16840+ pos; \
16841+ pos = pos->next)
16842+
16843+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl)
16844+{
16845+ unsigned long cnt;
16846+ struct hlist_bl_node *pos;
16847+
16848+ cnt = 0;
16849+ hlist_bl_lock(hbl);
16850+ au_hbl_for_each(pos, hbl)
16851+ cnt++;
16852+ hlist_bl_unlock(hbl);
16853+ return cnt;
16854+}
16855+
16856+#endif /* __KERNEL__ */
16857+#endif /* __AUFS_HBL_H__ */
7f207e10 16858diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
fbc438ed
JR
16859--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 08:00:00.000000000 +0800
16860+++ linux/fs/aufs/hfsnotify.c 2019-07-11 21:21:54.379051070 +0800
16861@@ -0,0 +1,288 @@
cd7a4cd9 16862+// SPDX-License-Identifier: GPL-2.0
1facf9fc 16863+/*
ba1aed25 16864+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 16865+ *
16866+ * This program, aufs is free software; you can redistribute it and/or modify
16867+ * it under the terms of the GNU General Public License as published by
16868+ * the Free Software Foundation; either version 2 of the License, or
16869+ * (at your option) any later version.
dece6358
AM
16870+ *
16871+ * This program is distributed in the hope that it will be useful,
16872+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16873+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16874+ * GNU General Public License for more details.
16875+ *
16876+ * You should have received a copy of the GNU General Public License
523b37e3 16877+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 16878+ */
16879+
16880+/*
4a4d8108 16881+ * fsnotify for the lower directories
1facf9fc 16882+ */
16883+
16884+#include "aufs.h"
16885+
4a4d8108
AM
16886+/* FS_IN_IGNORED is unnecessary */
16887+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
16888+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 16889+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 16890+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 16891+
0c5527e5 16892+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 16893+{
0c5527e5
AM
16894+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
16895+ hn_mark);
5afbbe0d 16896+ /* AuDbg("here\n"); */
1c60b727 16897+ au_cache_free_hnotify(hn);
8b6a4947 16898+ smp_mb__before_atomic(); /* for atomic64_dec */
1716fcea
AM
16899+ if (atomic64_dec_and_test(&au_hfsn_ifree))
16900+ wake_up(&au_hfsn_wq);
4a4d8108 16901+}
1facf9fc 16902+
027c5e7a 16903+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 16904+{
1716fcea 16905+ int err;
027c5e7a
AM
16906+ struct au_hnotify *hn;
16907+ struct super_block *sb;
16908+ struct au_branch *br;
0c5527e5 16909+ struct fsnotify_mark *mark;
027c5e7a 16910+ aufs_bindex_t bindex;
1facf9fc 16911+
027c5e7a
AM
16912+ hn = hinode->hi_notify;
16913+ sb = hn->hn_aufs_inode->i_sb;
16914+ bindex = au_br_index(sb, hinode->hi_id);
16915+ br = au_sbr(sb, bindex);
1716fcea
AM
16916+ AuDebugOn(!br->br_hfsn);
16917+
0c5527e5 16918+ mark = &hn->hn_mark;
ffa93bbd 16919+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group);
0c5527e5 16920+ mark->mask = AuHfsnMask;
7f207e10
AM
16921+ /*
16922+ * by udba rename or rmdir, aufs assign a new inode to the known
16923+ * h_inode, so specify 1 to allow dups.
16924+ */
c1595e42 16925+ lockdep_off();
acd2b654 16926+ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1);
c1595e42 16927+ lockdep_on();
1716fcea
AM
16928+
16929+ return err;
1facf9fc 16930+}
16931+
7eafdf33 16932+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 16933+{
0c5527e5 16934+ struct fsnotify_mark *mark;
7eafdf33 16935+ unsigned long long ull;
1716fcea 16936+ struct fsnotify_group *group;
7eafdf33
AM
16937+
16938+ ull = atomic64_inc_return(&au_hfsn_ifree);
16939+ BUG_ON(!ull);
953406b4 16940+
0c5527e5 16941+ mark = &hn->hn_mark;
1716fcea
AM
16942+ spin_lock(&mark->lock);
16943+ group = mark->group;
16944+ fsnotify_get_group(group);
16945+ spin_unlock(&mark->lock);
c1595e42 16946+ lockdep_off();
1716fcea 16947+ fsnotify_destroy_mark(mark, group);
5afbbe0d 16948+ fsnotify_put_mark(mark);
1716fcea 16949+ fsnotify_put_group(group);
c1595e42 16950+ lockdep_on();
7f207e10 16951+
7eafdf33
AM
16952+ /* free hn by myself */
16953+ return 0;
1facf9fc 16954+}
16955+
16956+/* ---------------------------------------------------------------------- */
16957+
4a4d8108 16958+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 16959+{
0c5527e5 16960+ struct fsnotify_mark *mark;
1facf9fc 16961+
0c5527e5
AM
16962+ mark = &hinode->hi_notify->hn_mark;
16963+ spin_lock(&mark->lock);
1facf9fc 16964+ if (do_set) {
0c5527e5
AM
16965+ AuDebugOn(mark->mask & AuHfsnMask);
16966+ mark->mask |= AuHfsnMask;
1facf9fc 16967+ } else {
0c5527e5
AM
16968+ AuDebugOn(!(mark->mask & AuHfsnMask));
16969+ mark->mask &= ~AuHfsnMask;
1facf9fc 16970+ }
0c5527e5 16971+ spin_unlock(&mark->lock);
4a4d8108 16972+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 16973+}
16974+
4a4d8108 16975+/* ---------------------------------------------------------------------- */
1facf9fc 16976+
4a4d8108
AM
16977+/* #define AuDbgHnotify */
16978+#ifdef AuDbgHnotify
16979+static char *au_hfsn_name(u32 mask)
16980+{
16981+#ifdef CONFIG_AUFS_DEBUG
c06a8ce3
AM
16982+#define test_ret(flag) \
16983+ do { \
16984+ if (mask & flag) \
16985+ return #flag; \
16986+ } while (0)
4a4d8108
AM
16987+ test_ret(FS_ACCESS);
16988+ test_ret(FS_MODIFY);
16989+ test_ret(FS_ATTRIB);
16990+ test_ret(FS_CLOSE_WRITE);
16991+ test_ret(FS_CLOSE_NOWRITE);
16992+ test_ret(FS_OPEN);
16993+ test_ret(FS_MOVED_FROM);
16994+ test_ret(FS_MOVED_TO);
16995+ test_ret(FS_CREATE);
16996+ test_ret(FS_DELETE);
16997+ test_ret(FS_DELETE_SELF);
16998+ test_ret(FS_MOVE_SELF);
16999+ test_ret(FS_UNMOUNT);
17000+ test_ret(FS_Q_OVERFLOW);
17001+ test_ret(FS_IN_IGNORED);
b912730e 17002+ test_ret(FS_ISDIR);
4a4d8108
AM
17003+ test_ret(FS_IN_ONESHOT);
17004+ test_ret(FS_EVENT_ON_CHILD);
17005+ return "";
17006+#undef test_ret
17007+#else
17008+ return "??";
17009+#endif
1facf9fc 17010+}
4a4d8108 17011+#endif
1facf9fc 17012+
17013+/* ---------------------------------------------------------------------- */
17014+
1716fcea
AM
17015+static void au_hfsn_free_group(struct fsnotify_group *group)
17016+{
17017+ struct au_br_hfsnotify *hfsn = group->private;
17018+
5afbbe0d 17019+ /* AuDbg("here\n"); */
9f237c51 17020+ au_kfree_try_rcu(hfsn);
1716fcea
AM
17021+}
17022+
4a4d8108 17023+static int au_hfsn_handle_event(struct fsnotify_group *group,
fb47a38f 17024+ struct inode *inode,
a2654f78 17025+ u32 mask, const void *data, int data_type,
83b672a5 17026+ const struct qstr *file_name, u32 cookie,
ffa93bbd 17027+ struct fsnotify_iter_info *iter_info)
1facf9fc 17028+{
17029+ int err;
4a4d8108
AM
17030+ struct au_hnotify *hnotify;
17031+ struct inode *h_dir, *h_inode;
cd7a4cd9 17032+ struct fsnotify_mark *inode_mark;
4a4d8108 17033+
fb47a38f 17034+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 17035+
17036+ err = 0;
0c5527e5 17037+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108 17038+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 17039+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 17040+ goto out;
1facf9fc 17041+
fb47a38f
JR
17042+ h_dir = inode;
17043+ h_inode = NULL;
4a4d8108 17044+#ifdef AuDbgHnotify
392086de 17045+ au_debug_on();
fbc438ed
JR
17046+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
17047+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
4a4d8108
AM
17048+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
17049+ h_dir->i_ino, mask, au_hfsn_name(mask),
fbc438ed 17050+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
4a4d8108 17051+ /* WARN_ON(1); */
1facf9fc 17052+ }
392086de 17053+ au_debug_off();
1facf9fc 17054+#endif
4a4d8108 17055+
cd7a4cd9 17056+ inode_mark = fsnotify_iter_inode_mark(iter_info);
0c5527e5
AM
17057+ AuDebugOn(!inode_mark);
17058+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
b62f1e65 17059+ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode);
1facf9fc 17060+
4a4d8108
AM
17061+out:
17062+ return err;
17063+}
1facf9fc 17064+
4a4d8108 17065+static struct fsnotify_ops au_hfsn_ops = {
1716fcea 17066+ .handle_event = au_hfsn_handle_event,
ffa93bbd
AM
17067+ .free_group_priv = au_hfsn_free_group,
17068+ .free_mark = au_hfsn_free_mark
4a4d8108
AM
17069+};
17070+
17071+/* ---------------------------------------------------------------------- */
17072+
027c5e7a
AM
17073+static void au_hfsn_fin_br(struct au_branch *br)
17074+{
1716fcea 17075+ struct au_br_hfsnotify *hfsn;
027c5e7a 17076+
1716fcea 17077+ hfsn = br->br_hfsn;
c1595e42
JR
17078+ if (hfsn) {
17079+ lockdep_off();
1716fcea 17080+ fsnotify_put_group(hfsn->hfsn_group);
c1595e42
JR
17081+ lockdep_on();
17082+ }
027c5e7a
AM
17083+}
17084+
1716fcea 17085+static int au_hfsn_init_br(struct au_branch *br, int perm)
4a4d8108
AM
17086+{
17087+ int err;
1716fcea
AM
17088+ struct fsnotify_group *group;
17089+ struct au_br_hfsnotify *hfsn;
1facf9fc 17090+
4a4d8108 17091+ err = 0;
1716fcea
AM
17092+ br->br_hfsn = NULL;
17093+ if (!au_br_hnotifyable(perm))
027c5e7a 17094+ goto out;
027c5e7a 17095+
1716fcea
AM
17096+ err = -ENOMEM;
17097+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS);
17098+ if (unlikely(!hfsn))
027c5e7a
AM
17099+ goto out;
17100+
1716fcea
AM
17101+ err = 0;
17102+ group = fsnotify_alloc_group(&au_hfsn_ops);
17103+ if (IS_ERR(group)) {
17104+ err = PTR_ERR(group);
0c5527e5 17105+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
1716fcea 17106+ goto out_hfsn;
4a4d8108 17107+ }
1facf9fc 17108+
1716fcea
AM
17109+ group->private = hfsn;
17110+ hfsn->hfsn_group = group;
17111+ br->br_hfsn = hfsn;
17112+ goto out; /* success */
17113+
17114+out_hfsn:
9f237c51 17115+ au_kfree_try_rcu(hfsn);
027c5e7a 17116+out:
1716fcea
AM
17117+ return err;
17118+}
17119+
17120+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
17121+{
17122+ int err;
17123+
17124+ err = 0;
17125+ if (!br->br_hfsn)
17126+ err = au_hfsn_init_br(br, perm);
17127+
1facf9fc 17128+ return err;
17129+}
17130+
7eafdf33
AM
17131+/* ---------------------------------------------------------------------- */
17132+
17133+static void au_hfsn_fin(void)
17134+{
17135+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
17136+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
17137+}
17138+
4a4d8108
AM
17139+const struct au_hnotify_op au_hnotify_op = {
17140+ .ctl = au_hfsn_ctl,
17141+ .alloc = au_hfsn_alloc,
17142+ .free = au_hfsn_free,
1facf9fc 17143+
7eafdf33
AM
17144+ .fin = au_hfsn_fin,
17145+
027c5e7a
AM
17146+ .reset_br = au_hfsn_reset_br,
17147+ .fin_br = au_hfsn_fin_br,
17148+ .init_br = au_hfsn_init_br
4a4d8108 17149+};
7f207e10 17150diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
fbc438ed
JR
17151--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 08:00:00.000000000 +0800
17152+++ linux/fs/aufs/hfsplus.c 2019-07-11 21:21:54.379051070 +0800
acd2b654 17153@@ -0,0 +1,60 @@
cd7a4cd9 17154+// SPDX-License-Identifier: GPL-2.0
4a4d8108 17155+/*
ba1aed25 17156+ * Copyright (C) 2010-2019 Junjiro R. Okajima
4a4d8108
AM
17157+ *
17158+ * This program, aufs is free software; you can redistribute it and/or modify
17159+ * it under the terms of the GNU General Public License as published by
17160+ * the Free Software Foundation; either version 2 of the License, or
17161+ * (at your option) any later version.
17162+ *
17163+ * This program is distributed in the hope that it will be useful,
17164+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17165+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17166+ * GNU General Public License for more details.
17167+ *
17168+ * You should have received a copy of the GNU General Public License
523b37e3 17169+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 17170+ */
1facf9fc 17171+
4a4d8108 17172+/*
acd2b654 17173+ * special support for filesystems which acquires an inode mutex
4a4d8108
AM
17174+ * at final closing a file, eg, hfsplus.
17175+ *
17176+ * This trick is very simple and stupid, just to open the file before really
acd2b654 17177+ * necessary open to tell hfsplus that this is not the final closing.
4a4d8108
AM
17178+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
17179+ * and au_h_open_post() after releasing it.
17180+ */
1facf9fc 17181+
4a4d8108 17182+#include "aufs.h"
1facf9fc 17183+
392086de
AM
17184+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
17185+ int force_wr)
4a4d8108
AM
17186+{
17187+ struct file *h_file;
17188+ struct dentry *h_dentry;
1facf9fc 17189+
4a4d8108
AM
17190+ h_dentry = au_h_dptr(dentry, bindex);
17191+ AuDebugOn(!h_dentry);
5527c038 17192+ AuDebugOn(d_is_negative(h_dentry));
4a4d8108
AM
17193+
17194+ h_file = NULL;
17195+ if (au_test_hfsplus(h_dentry->d_sb)
7e9cd9fe 17196+ && d_is_reg(h_dentry))
4a4d8108
AM
17197+ h_file = au_h_open(dentry, bindex,
17198+ O_RDONLY | O_NOATIME | O_LARGEFILE,
392086de 17199+ /*file*/NULL, force_wr);
4a4d8108 17200+ return h_file;
1facf9fc 17201+}
17202+
4a4d8108
AM
17203+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
17204+ struct file *h_file)
17205+{
acd2b654
AM
17206+ struct au_branch *br;
17207+
4a4d8108
AM
17208+ if (h_file) {
17209+ fput(h_file);
acd2b654
AM
17210+ br = au_sbr(dentry->d_sb, bindex);
17211+ au_lcnt_dec(&br->br_nfiles);
4a4d8108
AM
17212+ }
17213+}
7f207e10 17214diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
fbc438ed
JR
17215--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 08:00:00.000000000 +0800
17216+++ linux/fs/aufs/hnotify.c 2019-07-11 21:21:54.379051070 +0800
eca801bf 17217@@ -0,0 +1,721 @@
cd7a4cd9 17218+// SPDX-License-Identifier: GPL-2.0
e49829fe 17219+/*
ba1aed25 17220+ * Copyright (C) 2005-2019 Junjiro R. Okajima
e49829fe
JR
17221+ *
17222+ * This program, aufs is free software; you can redistribute it and/or modify
17223+ * it under the terms of the GNU General Public License as published by
17224+ * the Free Software Foundation; either version 2 of the License, or
17225+ * (at your option) any later version.
17226+ *
17227+ * This program is distributed in the hope that it will be useful,
17228+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17229+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17230+ * GNU General Public License for more details.
17231+ *
17232+ * You should have received a copy of the GNU General Public License
523b37e3 17233+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
17234+ */
17235+
17236+/*
7f207e10 17237+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
17238+ */
17239+
eca801bf 17240+/* #include <linux/iversion.h> */
e49829fe
JR
17241+#include "aufs.h"
17242+
027c5e7a 17243+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
17244+{
17245+ int err;
7f207e10 17246+ struct au_hnotify *hn;
1facf9fc 17247+
4a4d8108
AM
17248+ err = -ENOMEM;
17249+ hn = au_cache_alloc_hnotify();
17250+ if (hn) {
17251+ hn->hn_aufs_inode = inode;
027c5e7a
AM
17252+ hinode->hi_notify = hn;
17253+ err = au_hnotify_op.alloc(hinode);
17254+ AuTraceErr(err);
17255+ if (unlikely(err)) {
17256+ hinode->hi_notify = NULL;
1c60b727 17257+ au_cache_free_hnotify(hn);
4a4d8108
AM
17258+ /*
17259+ * The upper dir was removed by udba, but the same named
acd2b654 17260+ * dir left. In this case, aufs assigns a new inode
4a4d8108 17261+ * number and set the monitor again.
acd2b654 17262+ * For the lower dir, the old monitor is still left.
4a4d8108
AM
17263+ */
17264+ if (err == -EEXIST)
17265+ err = 0;
17266+ }
1308ab2a 17267+ }
1308ab2a 17268+
027c5e7a 17269+ AuTraceErr(err);
1308ab2a 17270+ return err;
dece6358 17271+}
1facf9fc 17272+
4a4d8108 17273+void au_hn_free(struct au_hinode *hinode)
dece6358 17274+{
4a4d8108 17275+ struct au_hnotify *hn;
1facf9fc 17276+
4a4d8108
AM
17277+ hn = hinode->hi_notify;
17278+ if (hn) {
4a4d8108 17279+ hinode->hi_notify = NULL;
7eafdf33 17280+ if (au_hnotify_op.free(hinode, hn))
1c60b727 17281+ au_cache_free_hnotify(hn);
4a4d8108
AM
17282+ }
17283+}
dece6358 17284+
4a4d8108 17285+/* ---------------------------------------------------------------------- */
dece6358 17286+
4a4d8108
AM
17287+void au_hn_ctl(struct au_hinode *hinode, int do_set)
17288+{
17289+ if (hinode->hi_notify)
17290+ au_hnotify_op.ctl(hinode, do_set);
17291+}
17292+
17293+void au_hn_reset(struct inode *inode, unsigned int flags)
17294+{
5afbbe0d 17295+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
17296+ struct inode *hi;
17297+ struct dentry *iwhdentry;
1facf9fc 17298+
5afbbe0d
AM
17299+ bbot = au_ibbot(inode);
17300+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108
AM
17301+ hi = au_h_iptr(inode, bindex);
17302+ if (!hi)
17303+ continue;
1308ab2a 17304+
febd17d6 17305+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */
4a4d8108
AM
17306+ iwhdentry = au_hi_wh(inode, bindex);
17307+ if (iwhdentry)
17308+ dget(iwhdentry);
17309+ au_igrab(hi);
17310+ au_set_h_iptr(inode, bindex, NULL, 0);
17311+ au_set_h_iptr(inode, bindex, au_igrab(hi),
17312+ flags & ~AuHi_XINO);
17313+ iput(hi);
17314+ dput(iwhdentry);
febd17d6 17315+ /* inode_unlock(hi); */
1facf9fc 17316+ }
1facf9fc 17317+}
17318+
1308ab2a 17319+/* ---------------------------------------------------------------------- */
1facf9fc 17320+
4a4d8108 17321+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 17322+{
4a4d8108 17323+ int err;
5afbbe0d 17324+ aufs_bindex_t bindex, bbot, bfound, btop;
4a4d8108 17325+ struct inode *h_i;
1facf9fc 17326+
4a4d8108
AM
17327+ err = 0;
17328+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17329+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17330+ goto out;
17331+ }
1facf9fc 17332+
4a4d8108 17333+ bfound = -1;
5afbbe0d
AM
17334+ bbot = au_ibbot(inode);
17335+ btop = au_ibtop(inode);
4a4d8108 17336+#if 0 /* reserved for future use */
5afbbe0d 17337+ if (bindex == bbot) {
4a4d8108
AM
17338+ /* keep this ino in rename case */
17339+ goto out;
17340+ }
17341+#endif
5afbbe0d 17342+ for (bindex = btop; bindex <= bbot; bindex++)
4a4d8108
AM
17343+ if (au_h_iptr(inode, bindex) == h_inode) {
17344+ bfound = bindex;
17345+ break;
17346+ }
17347+ if (bfound < 0)
1308ab2a 17348+ goto out;
1facf9fc 17349+
5afbbe0d 17350+ for (bindex = btop; bindex <= bbot; bindex++) {
4a4d8108
AM
17351+ h_i = au_h_iptr(inode, bindex);
17352+ if (!h_i)
17353+ continue;
1facf9fc 17354+
4a4d8108
AM
17355+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
17356+ /* ignore this error */
17357+ /* bad action? */
1facf9fc 17358+ }
1facf9fc 17359+
4a4d8108 17360+ /* children inode number will be broken */
1facf9fc 17361+
4f0767ce 17362+out:
4a4d8108
AM
17363+ AuTraceErr(err);
17364+ return err;
1facf9fc 17365+}
17366+
4a4d8108 17367+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 17368+{
4a4d8108
AM
17369+ int err, i, j, ndentry;
17370+ struct au_dcsub_pages dpages;
17371+ struct au_dpage *dpage;
17372+ struct dentry **dentries;
1facf9fc 17373+
4a4d8108
AM
17374+ err = au_dpages_init(&dpages, GFP_NOFS);
17375+ if (unlikely(err))
17376+ goto out;
17377+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
17378+ if (unlikely(err))
17379+ goto out_dpages;
1facf9fc 17380+
4a4d8108
AM
17381+ for (i = 0; i < dpages.ndpage; i++) {
17382+ dpage = dpages.dpages + i;
17383+ dentries = dpage->dentries;
17384+ ndentry = dpage->ndentry;
17385+ for (j = 0; j < ndentry; j++) {
17386+ struct dentry *d;
17387+
17388+ d = dentries[j];
17389+ if (IS_ROOT(d))
17390+ continue;
17391+
4a4d8108 17392+ au_digen_dec(d);
5527c038 17393+ if (d_really_is_positive(d))
4a4d8108
AM
17394+ /* todo: reset children xino?
17395+ cached children only? */
5527c038 17396+ au_iigen_dec(d_inode(d));
1308ab2a 17397+ }
dece6358 17398+ }
1facf9fc 17399+
4f0767ce 17400+out_dpages:
4a4d8108 17401+ au_dpages_free(&dpages);
dece6358 17402+
027c5e7a 17403+#if 0
4a4d8108
AM
17404+ /* discard children */
17405+ dentry_unhash(dentry);
17406+ dput(dentry);
027c5e7a 17407+#endif
4f0767ce 17408+out:
dece6358
AM
17409+ return err;
17410+}
17411+
1308ab2a 17412+/*
4a4d8108 17413+ * return 0 if processed.
1308ab2a 17414+ */
4a4d8108
AM
17415+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
17416+ const unsigned int isdir)
dece6358 17417+{
1308ab2a 17418+ int err;
4a4d8108
AM
17419+ struct dentry *d;
17420+ struct qstr *dname;
1facf9fc 17421+
4a4d8108
AM
17422+ err = 1;
17423+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17424+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17425+ err = 0;
17426+ goto out;
17427+ }
dece6358 17428+
4a4d8108
AM
17429+ if (!isdir) {
17430+ AuDebugOn(!name);
17431+ au_iigen_dec(inode);
027c5e7a 17432+ spin_lock(&inode->i_lock);
c1595e42 17433+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 17434+ spin_lock(&d->d_lock);
4a4d8108
AM
17435+ dname = &d->d_name;
17436+ if (dname->len != nlen
027c5e7a
AM
17437+ && memcmp(dname->name, name, nlen)) {
17438+ spin_unlock(&d->d_lock);
4a4d8108 17439+ continue;
027c5e7a 17440+ }
4a4d8108 17441+ err = 0;
4a4d8108
AM
17442+ au_digen_dec(d);
17443+ spin_unlock(&d->d_lock);
17444+ break;
1facf9fc 17445+ }
027c5e7a 17446+ spin_unlock(&inode->i_lock);
1308ab2a 17447+ } else {
027c5e7a 17448+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
c1595e42 17449+ d = d_find_any_alias(inode);
4a4d8108
AM
17450+ if (!d) {
17451+ au_iigen_dec(inode);
17452+ goto out;
17453+ }
1facf9fc 17454+
027c5e7a 17455+ spin_lock(&d->d_lock);
4a4d8108 17456+ dname = &d->d_name;
027c5e7a
AM
17457+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
17458+ spin_unlock(&d->d_lock);
4a4d8108 17459+ err = hn_gen_tree(d);
027c5e7a
AM
17460+ spin_lock(&d->d_lock);
17461+ }
17462+ spin_unlock(&d->d_lock);
4a4d8108
AM
17463+ dput(d);
17464+ }
1facf9fc 17465+
4f0767ce 17466+out:
4a4d8108 17467+ AuTraceErr(err);
1308ab2a 17468+ return err;
17469+}
dece6358 17470+
4a4d8108 17471+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 17472+{
4a4d8108 17473+ int err;
1facf9fc 17474+
5527c038 17475+ if (IS_ROOT(dentry)) {
0c3ec466 17476+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17477+ return 0;
17478+ }
1308ab2a 17479+
4a4d8108
AM
17480+ err = 0;
17481+ if (!isdir) {
4a4d8108 17482+ au_digen_dec(dentry);
5527c038
JR
17483+ if (d_really_is_positive(dentry))
17484+ au_iigen_dec(d_inode(dentry));
4a4d8108 17485+ } else {
027c5e7a 17486+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
5527c038 17487+ if (d_really_is_positive(dentry))
4a4d8108
AM
17488+ err = hn_gen_tree(dentry);
17489+ }
17490+
17491+ AuTraceErr(err);
17492+ return err;
1facf9fc 17493+}
17494+
4a4d8108 17495+/* ---------------------------------------------------------------------- */
1facf9fc 17496+
4a4d8108
AM
17497+/* hnotify job flags */
17498+#define AuHnJob_XINO0 1
17499+#define AuHnJob_GEN (1 << 1)
17500+#define AuHnJob_DIRENT (1 << 2)
17501+#define AuHnJob_ISDIR (1 << 3)
17502+#define AuHnJob_TRYXINO0 (1 << 4)
17503+#define AuHnJob_MNTPNT (1 << 5)
17504+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
17505+#define au_fset_hnjob(flags, name) \
17506+ do { (flags) |= AuHnJob_##name; } while (0)
17507+#define au_fclr_hnjob(flags, name) \
17508+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 17509+
4a4d8108
AM
17510+enum {
17511+ AuHn_CHILD,
17512+ AuHn_PARENT,
17513+ AuHnLast
17514+};
1facf9fc 17515+
4a4d8108
AM
17516+struct au_hnotify_args {
17517+ struct inode *h_dir, *dir, *h_child_inode;
17518+ u32 mask;
17519+ unsigned int flags[AuHnLast];
17520+ unsigned int h_child_nlen;
17521+ char h_child_name[];
17522+};
1facf9fc 17523+
4a4d8108
AM
17524+struct hn_job_args {
17525+ unsigned int flags;
17526+ struct inode *inode, *h_inode, *dir, *h_dir;
17527+ struct dentry *dentry;
17528+ char *h_name;
17529+ int h_nlen;
17530+};
1308ab2a 17531+
4a4d8108
AM
17532+static int hn_job(struct hn_job_args *a)
17533+{
17534+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
076b876e 17535+ int e;
1308ab2a 17536+
4a4d8108
AM
17537+ /* reset xino */
17538+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
17539+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 17540+
4a4d8108
AM
17541+ if (au_ftest_hnjob(a->flags, TRYXINO0)
17542+ && a->inode
17543+ && a->h_inode) {
be118d29 17544+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
38d290e6
JR
17545+ if (!a->h_inode->i_nlink
17546+ && !(a->h_inode->i_state & I_LINKABLE))
4a4d8108 17547+ hn_xino(a->inode, a->h_inode); /* ignore this error */
3c1bdaff 17548+ inode_unlock_shared(a->h_inode);
1308ab2a 17549+ }
1facf9fc 17550+
4a4d8108
AM
17551+ /* make the generation obsolete */
17552+ if (au_ftest_hnjob(a->flags, GEN)) {
076b876e 17553+ e = -1;
4a4d8108 17554+ if (a->inode)
076b876e 17555+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
4a4d8108 17556+ isdir);
076b876e 17557+ if (e && a->dentry)
4a4d8108
AM
17558+ hn_gen_by_name(a->dentry, isdir);
17559+ /* ignore this error */
1facf9fc 17560+ }
1facf9fc 17561+
4a4d8108
AM
17562+ /* make dir entries obsolete */
17563+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
17564+ struct au_vdir *vdir;
1facf9fc 17565+
4a4d8108
AM
17566+ vdir = au_ivdir(a->inode);
17567+ if (vdir)
17568+ vdir->vd_jiffy = 0;
17569+ /* IMustLock(a->inode); */
be118d29 17570+ /* inode_inc_iversion(a->inode); */
4a4d8108 17571+ }
1facf9fc 17572+
4a4d8108
AM
17573+ /* can do nothing but warn */
17574+ if (au_ftest_hnjob(a->flags, MNTPNT)
17575+ && a->dentry
17576+ && d_mountpoint(a->dentry))
523b37e3 17577+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry);
1facf9fc 17578+
4a4d8108 17579+ return 0;
1308ab2a 17580+}
1facf9fc 17581+
1308ab2a 17582+/* ---------------------------------------------------------------------- */
1facf9fc 17583+
4a4d8108
AM
17584+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
17585+ struct inode *dir)
1308ab2a 17586+{
4a4d8108
AM
17587+ struct dentry *dentry, *d, *parent;
17588+ struct qstr *dname;
1308ab2a 17589+
c1595e42 17590+ parent = d_find_any_alias(dir);
4a4d8108
AM
17591+ if (!parent)
17592+ return NULL;
1308ab2a 17593+
4a4d8108 17594+ dentry = NULL;
027c5e7a 17595+ spin_lock(&parent->d_lock);
c1595e42 17596+ list_for_each_entry(d, &parent->d_subdirs, d_child) {
523b37e3 17597+ /* AuDbg("%pd\n", d); */
027c5e7a 17598+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
17599+ dname = &d->d_name;
17600+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
17601+ goto cont_unlock;
17602+ if (au_di(d))
17603+ au_digen_dec(d);
17604+ else
17605+ goto cont_unlock;
c1595e42 17606+ if (au_dcount(d) > 0) {
027c5e7a 17607+ dentry = dget_dlock(d);
4a4d8108 17608+ spin_unlock(&d->d_lock);
027c5e7a 17609+ break;
dece6358 17610+ }
1facf9fc 17611+
f6b6e03d 17612+cont_unlock:
027c5e7a 17613+ spin_unlock(&d->d_lock);
1308ab2a 17614+ }
027c5e7a 17615+ spin_unlock(&parent->d_lock);
4a4d8108 17616+ dput(parent);
1facf9fc 17617+
4a4d8108
AM
17618+ if (dentry)
17619+ di_write_lock_child(dentry);
1308ab2a 17620+
4a4d8108
AM
17621+ return dentry;
17622+}
dece6358 17623+
4a4d8108
AM
17624+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
17625+ aufs_bindex_t bindex, ino_t h_ino)
17626+{
17627+ struct inode *inode;
17628+ ino_t ino;
17629+ int err;
17630+
17631+ inode = NULL;
17632+ err = au_xino_read(sb, bindex, h_ino, &ino);
17633+ if (!err && ino)
17634+ inode = ilookup(sb, ino);
17635+ if (!inode)
17636+ goto out;
17637+
17638+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17639+ pr_warn("wrong root branch\n");
4a4d8108
AM
17640+ iput(inode);
17641+ inode = NULL;
17642+ goto out;
1308ab2a 17643+ }
17644+
4a4d8108 17645+ ii_write_lock_child(inode);
1308ab2a 17646+
4f0767ce 17647+out:
4a4d8108 17648+ return inode;
dece6358
AM
17649+}
17650+
4a4d8108 17651+static void au_hn_bh(void *_args)
1facf9fc 17652+{
4a4d8108
AM
17653+ struct au_hnotify_args *a = _args;
17654+ struct super_block *sb;
5afbbe0d 17655+ aufs_bindex_t bindex, bbot, bfound;
4a4d8108 17656+ unsigned char xino, try_iput;
1facf9fc 17657+ int err;
1308ab2a 17658+ struct inode *inode;
4a4d8108
AM
17659+ ino_t h_ino;
17660+ struct hn_job_args args;
17661+ struct dentry *dentry;
17662+ struct au_sbinfo *sbinfo;
1facf9fc 17663+
4a4d8108
AM
17664+ AuDebugOn(!_args);
17665+ AuDebugOn(!a->h_dir);
17666+ AuDebugOn(!a->dir);
17667+ AuDebugOn(!a->mask);
17668+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
17669+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
17670+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 17671+
4a4d8108
AM
17672+ inode = NULL;
17673+ dentry = NULL;
17674+ /*
17675+ * do not lock a->dir->i_mutex here
17676+ * because of d_revalidate() may cause a deadlock.
17677+ */
17678+ sb = a->dir->i_sb;
17679+ AuDebugOn(!sb);
17680+ sbinfo = au_sbi(sb);
17681+ AuDebugOn(!sbinfo);
7f207e10 17682+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 17683+
8b6a4947
AM
17684+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
17685+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) {
17686+ case FS_MOVED_FROM:
17687+ case FS_MOVED_TO:
17688+ AuWarn1("DIRREN with UDBA may not work correctly "
17689+ "for the direct rename(2)\n");
17690+ }
17691+
4a4d8108
AM
17692+ ii_read_lock_parent(a->dir);
17693+ bfound = -1;
5afbbe0d
AM
17694+ bbot = au_ibbot(a->dir);
17695+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++)
4a4d8108
AM
17696+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
17697+ bfound = bindex;
17698+ break;
17699+ }
17700+ ii_read_unlock(a->dir);
17701+ if (unlikely(bfound < 0))
17702+ goto out;
1facf9fc 17703+
4a4d8108
AM
17704+ xino = !!au_opt_test(au_mntflags(sb), XINO);
17705+ h_ino = 0;
17706+ if (a->h_child_inode)
17707+ h_ino = a->h_child_inode->i_ino;
1facf9fc 17708+
4a4d8108
AM
17709+ if (a->h_child_nlen
17710+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
17711+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
17712+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
17713+ a->dir);
17714+ try_iput = 0;
5527c038
JR
17715+ if (dentry && d_really_is_positive(dentry))
17716+ inode = d_inode(dentry);
4a4d8108
AM
17717+ if (xino && !inode && h_ino
17718+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
17719+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
17720+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
17721+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
17722+ try_iput = 1;
f0c0a007 17723+ }
1facf9fc 17724+
4a4d8108
AM
17725+ args.flags = a->flags[AuHn_CHILD];
17726+ args.dentry = dentry;
17727+ args.inode = inode;
17728+ args.h_inode = a->h_child_inode;
17729+ args.dir = a->dir;
17730+ args.h_dir = a->h_dir;
17731+ args.h_name = a->h_child_name;
17732+ args.h_nlen = a->h_child_nlen;
17733+ err = hn_job(&args);
17734+ if (dentry) {
027c5e7a 17735+ if (au_di(dentry))
4a4d8108
AM
17736+ di_write_unlock(dentry);
17737+ dput(dentry);
17738+ }
17739+ if (inode && try_iput) {
17740+ ii_write_unlock(inode);
17741+ iput(inode);
17742+ }
1facf9fc 17743+
4a4d8108
AM
17744+ ii_write_lock_parent(a->dir);
17745+ args.flags = a->flags[AuHn_PARENT];
17746+ args.dentry = NULL;
17747+ args.inode = a->dir;
17748+ args.h_inode = a->h_dir;
17749+ args.dir = NULL;
17750+ args.h_dir = NULL;
17751+ args.h_name = NULL;
17752+ args.h_nlen = 0;
17753+ err = hn_job(&args);
17754+ ii_write_unlock(a->dir);
1facf9fc 17755+
4f0767ce 17756+out:
4a4d8108
AM
17757+ iput(a->h_child_inode);
17758+ iput(a->h_dir);
17759+ iput(a->dir);
027c5e7a
AM
17760+ si_write_unlock(sb);
17761+ au_nwt_done(&sbinfo->si_nowait);
9f237c51 17762+ au_kfree_rcu(a);
dece6358 17763+}
1facf9fc 17764+
4a4d8108
AM
17765+/* ---------------------------------------------------------------------- */
17766+
17767+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
b62f1e65 17768+ const struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 17769+{
4a4d8108 17770+ int err, len;
53392da6 17771+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
17772+ unsigned char isdir, isroot, wh;
17773+ struct inode *dir;
17774+ struct au_hnotify_args *args;
17775+ char *p, *h_child_name;
dece6358 17776+
1308ab2a 17777+ err = 0;
4a4d8108
AM
17778+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
17779+ dir = igrab(hnotify->hn_aufs_inode);
17780+ if (!dir)
17781+ goto out;
1facf9fc 17782+
4a4d8108
AM
17783+ isroot = (dir->i_ino == AUFS_ROOT_INO);
17784+ wh = 0;
17785+ h_child_name = (void *)h_child_qstr->name;
17786+ len = h_child_qstr->len;
17787+ if (h_child_name) {
17788+ if (len > AUFS_WH_PFX_LEN
17789+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
17790+ h_child_name += AUFS_WH_PFX_LEN;
17791+ len -= AUFS_WH_PFX_LEN;
17792+ wh = 1;
17793+ }
1facf9fc 17794+ }
dece6358 17795+
4a4d8108
AM
17796+ isdir = 0;
17797+ if (h_child_inode)
17798+ isdir = !!S_ISDIR(h_child_inode->i_mode);
17799+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
17800+ flags[AuHn_CHILD] = 0;
17801+ if (isdir)
17802+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
17803+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
17804+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
fbc438ed 17805+ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) {
4a4d8108
AM
17806+ case FS_MOVED_FROM:
17807+ case FS_MOVED_TO:
17808+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
17809+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
17810+ /*FALLTHROUGH*/
17811+ case FS_CREATE:
fb47a38f 17812+ AuDebugOn(!h_child_name);
4a4d8108 17813+ break;
1facf9fc 17814+
4a4d8108
AM
17815+ case FS_DELETE:
17816+ /*
17817+ * aufs never be able to get this child inode.
17818+ * revalidation should be in d_revalidate()
17819+ * by checking i_nlink, i_generation or d_unhashed().
17820+ */
17821+ AuDebugOn(!h_child_name);
17822+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
17823+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
17824+ break;
dece6358 17825+
4a4d8108
AM
17826+ default:
17827+ AuDebugOn(1);
17828+ }
1308ab2a 17829+
4a4d8108
AM
17830+ if (wh)
17831+ h_child_inode = NULL;
1308ab2a 17832+
4a4d8108
AM
17833+ err = -ENOMEM;
17834+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 17835+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
17836+ if (unlikely(!args)) {
17837+ AuErr1("no memory\n");
17838+ iput(dir);
17839+ goto out;
17840+ }
17841+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
17842+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
17843+ args->mask = mask;
17844+ args->dir = dir;
17845+ args->h_dir = igrab(h_dir);
17846+ if (h_child_inode)
17847+ h_child_inode = igrab(h_child_inode); /* can be NULL */
17848+ args->h_child_inode = h_child_inode;
17849+ args->h_child_nlen = len;
17850+ if (len) {
17851+ p = (void *)args;
17852+ p += sizeof(*args);
17853+ memcpy(p, h_child_name, len);
17854+ p[len] = 0;
1308ab2a 17855+ }
1308ab2a 17856+
38d290e6 17857+ /* NFS fires the event for silly-renamed one from kworker */
53392da6 17858+ f = 0;
38d290e6
JR
17859+ if (!dir->i_nlink
17860+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE)))
53392da6
AM
17861+ f = AuWkq_NEST;
17862+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
17863+ if (unlikely(err)) {
17864+ pr_err("wkq %d\n", err);
17865+ iput(args->h_child_inode);
17866+ iput(args->h_dir);
17867+ iput(args->dir);
9f237c51 17868+ au_kfree_rcu(args);
1facf9fc 17869+ }
1facf9fc 17870+
4a4d8108 17871+out:
1facf9fc 17872+ return err;
17873+}
17874+
027c5e7a
AM
17875+/* ---------------------------------------------------------------------- */
17876+
17877+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
17878+{
17879+ int err;
17880+
17881+ AuDebugOn(!(udba & AuOptMask_UDBA));
17882+
17883+ err = 0;
17884+ if (au_hnotify_op.reset_br)
17885+ err = au_hnotify_op.reset_br(udba, br, perm);
17886+
17887+ return err;
17888+}
17889+
17890+int au_hnotify_init_br(struct au_branch *br, int perm)
17891+{
17892+ int err;
17893+
17894+ err = 0;
17895+ if (au_hnotify_op.init_br)
17896+ err = au_hnotify_op.init_br(br, perm);
17897+
17898+ return err;
17899+}
17900+
17901+void au_hnotify_fin_br(struct au_branch *br)
17902+{
17903+ if (au_hnotify_op.fin_br)
17904+ au_hnotify_op.fin_br(br);
17905+}
17906+
4a4d8108
AM
17907+static void au_hn_destroy_cache(void)
17908+{
1c60b727
AM
17909+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]);
17910+ au_cache[AuCache_HNOTIFY] = NULL;
4a4d8108 17911+}
1308ab2a 17912+
4a4d8108 17913+int __init au_hnotify_init(void)
1facf9fc 17914+{
1308ab2a 17915+ int err;
1308ab2a 17916+
4a4d8108 17917+ err = -ENOMEM;
1c60b727
AM
17918+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify);
17919+ if (au_cache[AuCache_HNOTIFY]) {
027c5e7a
AM
17920+ err = 0;
17921+ if (au_hnotify_op.init)
17922+ err = au_hnotify_op.init();
4a4d8108
AM
17923+ if (unlikely(err))
17924+ au_hn_destroy_cache();
1308ab2a 17925+ }
1308ab2a 17926+ AuTraceErr(err);
4a4d8108 17927+ return err;
1308ab2a 17928+}
17929+
4a4d8108 17930+void au_hnotify_fin(void)
1308ab2a 17931+{
027c5e7a
AM
17932+ if (au_hnotify_op.fin)
17933+ au_hnotify_op.fin();
f0c0a007 17934+
4a4d8108 17935+ /* cf. au_cache_fin() */
1c60b727 17936+ if (au_cache[AuCache_HNOTIFY])
4a4d8108 17937+ au_hn_destroy_cache();
dece6358 17938+}
7f207e10 17939diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
fbc438ed
JR
17940--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 08:00:00.000000000 +0800
17941+++ linux/fs/aufs/iinfo.c 2019-07-11 21:21:54.382384486 +0800
062440b3 17942@@ -0,0 +1,286 @@
cd7a4cd9 17943+// SPDX-License-Identifier: GPL-2.0
dece6358 17944+/*
ba1aed25 17945+ * Copyright (C) 2005-2019 Junjiro R. Okajima
dece6358
AM
17946+ *
17947+ * This program, aufs is free software; you can redistribute it and/or modify
17948+ * it under the terms of the GNU General Public License as published by
17949+ * the Free Software Foundation; either version 2 of the License, or
17950+ * (at your option) any later version.
17951+ *
17952+ * This program is distributed in the hope that it will be useful,
17953+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17954+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17955+ * GNU General Public License for more details.
17956+ *
17957+ * You should have received a copy of the GNU General Public License
523b37e3 17958+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 17959+ */
1facf9fc 17960+
dece6358 17961+/*
4a4d8108 17962+ * inode private data
dece6358 17963+ */
1facf9fc 17964+
1308ab2a 17965+#include "aufs.h"
1facf9fc 17966+
4a4d8108 17967+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 17968+{
4a4d8108 17969+ struct inode *h_inode;
5afbbe0d 17970+ struct au_hinode *hinode;
1facf9fc 17971+
4a4d8108 17972+ IiMustAnyLock(inode);
1facf9fc 17973+
5afbbe0d
AM
17974+ hinode = au_hinode(au_ii(inode), bindex);
17975+ h_inode = hinode->hi_inode;
4a4d8108
AM
17976+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
17977+ return h_inode;
17978+}
1facf9fc 17979+
4a4d8108
AM
17980+/* todo: hard/soft set? */
17981+void au_hiput(struct au_hinode *hinode)
17982+{
17983+ au_hn_free(hinode);
17984+ dput(hinode->hi_whdentry);
17985+ iput(hinode->hi_inode);
17986+}
1facf9fc 17987+
4a4d8108
AM
17988+unsigned int au_hi_flags(struct inode *inode, int isdir)
17989+{
17990+ unsigned int flags;
17991+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 17992+
4a4d8108
AM
17993+ flags = 0;
17994+ if (au_opt_test(mnt_flags, XINO))
17995+ au_fset_hi(flags, XINO);
17996+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
17997+ au_fset_hi(flags, HNOTIFY);
17998+ return flags;
1facf9fc 17999+}
18000+
4a4d8108
AM
18001+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
18002+ struct inode *h_inode, unsigned int flags)
1308ab2a 18003+{
4a4d8108
AM
18004+ struct au_hinode *hinode;
18005+ struct inode *hi;
18006+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 18007+
4a4d8108 18008+ IiMustWriteLock(inode);
dece6358 18009+
5afbbe0d 18010+ hinode = au_hinode(iinfo, bindex);
4a4d8108
AM
18011+ hi = hinode->hi_inode;
18012+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
18013+
18014+ if (hi)
18015+ au_hiput(hinode);
18016+ hinode->hi_inode = h_inode;
18017+ if (h_inode) {
18018+ int err;
18019+ struct super_block *sb = inode->i_sb;
18020+ struct au_branch *br;
18021+
027c5e7a
AM
18022+ AuDebugOn(inode->i_mode
18023+ && (h_inode->i_mode & S_IFMT)
18024+ != (inode->i_mode & S_IFMT));
5afbbe0d 18025+ if (bindex == iinfo->ii_btop)
4a4d8108
AM
18026+ au_cpup_igen(inode, h_inode);
18027+ br = au_sbr(sb, bindex);
18028+ hinode->hi_id = br->br_id;
18029+ if (au_ftest_hi(flags, XINO)) {
18030+ err = au_xino_write(sb, bindex, h_inode->i_ino,
18031+ inode->i_ino);
18032+ if (unlikely(err))
18033+ AuIOErr1("failed au_xino_write() %d\n", err);
18034+ }
18035+
18036+ if (au_ftest_hi(flags, HNOTIFY)
18037+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 18038+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
18039+ if (unlikely(err))
18040+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 18041+ }
18042+ }
4a4d8108 18043+}
dece6358 18044+
4a4d8108
AM
18045+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
18046+ struct dentry *h_wh)
18047+{
18048+ struct au_hinode *hinode;
dece6358 18049+
4a4d8108
AM
18050+ IiMustWriteLock(inode);
18051+
5afbbe0d 18052+ hinode = au_hinode(au_ii(inode), bindex);
4a4d8108
AM
18053+ AuDebugOn(hinode->hi_whdentry);
18054+ hinode->hi_whdentry = h_wh;
1facf9fc 18055+}
18056+
537831f9 18057+void au_update_iigen(struct inode *inode, int half)
1308ab2a 18058+{
537831f9
AM
18059+ struct au_iinfo *iinfo;
18060+ struct au_iigen *iigen;
18061+ unsigned int sigen;
18062+
18063+ sigen = au_sigen(inode->i_sb);
18064+ iinfo = au_ii(inode);
18065+ iigen = &iinfo->ii_generation;
be52b249 18066+ spin_lock(&iigen->ig_spin);
537831f9
AM
18067+ iigen->ig_generation = sigen;
18068+ if (half)
18069+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED);
18070+ else
18071+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED);
be52b249 18072+ spin_unlock(&iigen->ig_spin);
4a4d8108 18073+}
1facf9fc 18074+
4a4d8108
AM
18075+/* it may be called at remount time, too */
18076+void au_update_ibrange(struct inode *inode, int do_put_zero)
18077+{
18078+ struct au_iinfo *iinfo;
5afbbe0d 18079+ aufs_bindex_t bindex, bbot;
1facf9fc 18080+
5afbbe0d 18081+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 18082+ IiMustWriteLock(inode);
1facf9fc 18083+
5afbbe0d
AM
18084+ iinfo = au_ii(inode);
18085+ if (do_put_zero && iinfo->ii_btop >= 0) {
18086+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
18087+ bindex++) {
18088+ struct inode *h_i;
1facf9fc 18089+
5afbbe0d 18090+ h_i = au_hinode(iinfo, bindex)->hi_inode;
38d290e6
JR
18091+ if (h_i
18092+ && !h_i->i_nlink
18093+ && !(h_i->i_state & I_LINKABLE))
027c5e7a
AM
18094+ au_set_h_iptr(inode, bindex, NULL, 0);
18095+ }
4a4d8108
AM
18096+ }
18097+
5afbbe0d
AM
18098+ iinfo->ii_btop = -1;
18099+ iinfo->ii_bbot = -1;
18100+ bbot = au_sbbot(inode->i_sb);
18101+ for (bindex = 0; bindex <= bbot; bindex++)
18102+ if (au_hinode(iinfo, bindex)->hi_inode) {
18103+ iinfo->ii_btop = bindex;
4a4d8108 18104+ break;
027c5e7a 18105+ }
5afbbe0d
AM
18106+ if (iinfo->ii_btop >= 0)
18107+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--)
18108+ if (au_hinode(iinfo, bindex)->hi_inode) {
18109+ iinfo->ii_bbot = bindex;
027c5e7a
AM
18110+ break;
18111+ }
5afbbe0d 18112+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot);
1308ab2a 18113+}
1facf9fc 18114+
dece6358 18115+/* ---------------------------------------------------------------------- */
1facf9fc 18116+
4a4d8108 18117+void au_icntnr_init_once(void *_c)
dece6358 18118+{
4a4d8108
AM
18119+ struct au_icntnr *c = _c;
18120+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 18121+
be52b249 18122+ spin_lock_init(&iinfo->ii_generation.ig_spin);
4a4d8108
AM
18123+ au_rw_init(&iinfo->ii_rwsem);
18124+ inode_init_once(&c->vfs_inode);
18125+}
1facf9fc 18126+
5afbbe0d
AM
18127+void au_hinode_init(struct au_hinode *hinode)
18128+{
18129+ hinode->hi_inode = NULL;
18130+ hinode->hi_id = -1;
18131+ au_hn_init(hinode);
18132+ hinode->hi_whdentry = NULL;
18133+}
18134+
4a4d8108
AM
18135+int au_iinfo_init(struct inode *inode)
18136+{
18137+ struct au_iinfo *iinfo;
18138+ struct super_block *sb;
5afbbe0d 18139+ struct au_hinode *hi;
4a4d8108 18140+ int nbr, i;
1facf9fc 18141+
4a4d8108
AM
18142+ sb = inode->i_sb;
18143+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
5afbbe0d 18144+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
18145+ if (unlikely(nbr <= 0))
18146+ nbr = 1;
5afbbe0d
AM
18147+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
18148+ if (hi) {
acd2b654 18149+ au_lcnt_inc(&au_sbi(sb)->si_ninodes);
5afbbe0d
AM
18150+
18151+ iinfo->ii_hinode = hi;
18152+ for (i = 0; i < nbr; i++, hi++)
18153+ au_hinode_init(hi);
1facf9fc 18154+
537831f9 18155+ iinfo->ii_generation.ig_generation = au_sigen(sb);
5afbbe0d
AM
18156+ iinfo->ii_btop = -1;
18157+ iinfo->ii_bbot = -1;
4a4d8108
AM
18158+ iinfo->ii_vdir = NULL;
18159+ return 0;
1308ab2a 18160+ }
4a4d8108
AM
18161+ return -ENOMEM;
18162+}
1facf9fc 18163+
e2f27e51 18164+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink)
4a4d8108 18165+{
5afbbe0d 18166+ int err, i;
4a4d8108 18167+ struct au_hinode *hip;
1facf9fc 18168+
4a4d8108
AM
18169+ AuRwMustWriteLock(&iinfo->ii_rwsem);
18170+
18171+ err = -ENOMEM;
e2f27e51
AM
18172+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS,
18173+ may_shrink);
4a4d8108
AM
18174+ if (hip) {
18175+ iinfo->ii_hinode = hip;
5afbbe0d
AM
18176+ i = iinfo->ii_bbot + 1;
18177+ hip += i;
18178+ for (; i < nbr; i++, hip++)
18179+ au_hinode_init(hip);
4a4d8108 18180+ err = 0;
1308ab2a 18181+ }
4a4d8108 18182+
1308ab2a 18183+ return err;
1facf9fc 18184+}
18185+
4a4d8108 18186+void au_iinfo_fin(struct inode *inode)
1facf9fc 18187+{
4a4d8108
AM
18188+ struct au_iinfo *iinfo;
18189+ struct au_hinode *hi;
18190+ struct super_block *sb;
5afbbe0d 18191+ aufs_bindex_t bindex, bbot;
b752ccd1 18192+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 18193+
5afbbe0d 18194+ AuDebugOn(au_is_bad_inode(inode));
1308ab2a 18195+
b752ccd1 18196+ sb = inode->i_sb;
acd2b654 18197+ au_lcnt_dec(&au_sbi(sb)->si_ninodes);
b752ccd1
AM
18198+ if (si_pid_test(sb))
18199+ au_xino_delete_inode(inode, unlinked);
18200+ else {
18201+ /*
18202+ * it is safe to hide the dependency between sbinfo and
18203+ * sb->s_umount.
18204+ */
18205+ lockdep_off();
18206+ si_noflush_read_lock(sb);
18207+ au_xino_delete_inode(inode, unlinked);
18208+ si_read_unlock(sb);
18209+ lockdep_on();
18210+ }
18211+
5afbbe0d 18212+ iinfo = au_ii(inode);
4a4d8108 18213+ if (iinfo->ii_vdir)
1c60b727 18214+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 18215+
5afbbe0d 18216+ bindex = iinfo->ii_btop;
b752ccd1 18217+ if (bindex >= 0) {
5afbbe0d
AM
18218+ hi = au_hinode(iinfo, bindex);
18219+ bbot = iinfo->ii_bbot;
18220+ while (bindex++ <= bbot) {
b752ccd1 18221+ if (hi->hi_inode)
4a4d8108 18222+ au_hiput(hi);
4a4d8108
AM
18223+ hi++;
18224+ }
18225+ }
9f237c51 18226+ au_kfree_rcu(iinfo->ii_hinode);
4a4d8108 18227+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 18228+}
7f207e10 18229diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
fbc438ed
JR
18230--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 08:00:00.000000000 +0800
18231+++ linux/fs/aufs/inode.c 2019-07-11 21:21:54.382384486 +0800
eca801bf 18232@@ -0,0 +1,529 @@
cd7a4cd9 18233+// SPDX-License-Identifier: GPL-2.0
4a4d8108 18234+/*
ba1aed25 18235+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
18236+ *
18237+ * This program, aufs is free software; you can redistribute it and/or modify
18238+ * it under the terms of the GNU General Public License as published by
18239+ * the Free Software Foundation; either version 2 of the License, or
18240+ * (at your option) any later version.
18241+ *
18242+ * This program is distributed in the hope that it will be useful,
18243+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18244+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18245+ * GNU General Public License for more details.
18246+ *
18247+ * You should have received a copy of the GNU General Public License
523b37e3 18248+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18249+ */
1facf9fc 18250+
4a4d8108
AM
18251+/*
18252+ * inode functions
18253+ */
1facf9fc 18254+
eca801bf 18255+#include <linux/iversion.h>
4a4d8108 18256+#include "aufs.h"
1308ab2a 18257+
4a4d8108
AM
18258+struct inode *au_igrab(struct inode *inode)
18259+{
18260+ if (inode) {
18261+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 18262+ ihold(inode);
1facf9fc 18263+ }
4a4d8108
AM
18264+ return inode;
18265+}
1facf9fc 18266+
4a4d8108
AM
18267+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
18268+{
18269+ au_cpup_attr_all(inode, /*force*/0);
537831f9 18270+ au_update_iigen(inode, /*half*/1);
4a4d8108 18271+ if (do_version)
be118d29 18272+ inode_inc_iversion(inode);
dece6358 18273+}
1facf9fc 18274+
027c5e7a 18275+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 18276+{
e2f27e51 18277+ int err, e, nbr;
027c5e7a 18278+ umode_t type;
4a4d8108 18279+ aufs_bindex_t bindex, new_bindex;
1308ab2a 18280+ struct super_block *sb;
4a4d8108 18281+ struct au_iinfo *iinfo;
027c5e7a 18282+ struct au_hinode *p, *q, tmp;
1facf9fc 18283+
5afbbe0d 18284+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 18285+ IiMustWriteLock(inode);
1facf9fc 18286+
027c5e7a 18287+ *update = 0;
4a4d8108 18288+ sb = inode->i_sb;
e2f27e51 18289+ nbr = au_sbbot(sb) + 1;
027c5e7a 18290+ type = inode->i_mode & S_IFMT;
4a4d8108 18291+ iinfo = au_ii(inode);
e2f27e51 18292+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0);
4a4d8108 18293+ if (unlikely(err))
1308ab2a 18294+ goto out;
1facf9fc 18295+
5afbbe0d
AM
18296+ AuDebugOn(iinfo->ii_btop < 0);
18297+ p = au_hinode(iinfo, iinfo->ii_btop);
18298+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
18299+ bindex++, p++) {
18300+ if (!p->hi_inode)
18301+ continue;
1facf9fc 18302+
027c5e7a 18303+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
18304+ new_bindex = au_br_index(sb, p->hi_id);
18305+ if (new_bindex == bindex)
18306+ continue;
1facf9fc 18307+
4a4d8108 18308+ if (new_bindex < 0) {
027c5e7a 18309+ *update = 1;
4a4d8108
AM
18310+ au_hiput(p);
18311+ p->hi_inode = NULL;
18312+ continue;
1308ab2a 18313+ }
4a4d8108 18314+
5afbbe0d
AM
18315+ if (new_bindex < iinfo->ii_btop)
18316+ iinfo->ii_btop = new_bindex;
18317+ if (iinfo->ii_bbot < new_bindex)
18318+ iinfo->ii_bbot = new_bindex;
4a4d8108 18319+ /* swap two lower inode, and loop again */
5afbbe0d 18320+ q = au_hinode(iinfo, new_bindex);
4a4d8108
AM
18321+ tmp = *q;
18322+ *q = *p;
18323+ *p = tmp;
18324+ if (tmp.hi_inode) {
18325+ bindex--;
18326+ p--;
1308ab2a 18327+ }
18328+ }
4a4d8108 18329+ au_update_ibrange(inode, /*do_put_zero*/0);
e2f27e51 18330+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */
4a4d8108
AM
18331+ e = au_dy_irefresh(inode);
18332+ if (unlikely(e && !err))
18333+ err = e;
1facf9fc 18334+
4f0767ce 18335+out:
027c5e7a
AM
18336+ AuTraceErr(err);
18337+ return err;
18338+}
18339+
b95c5147
AM
18340+void au_refresh_iop(struct inode *inode, int force_getattr)
18341+{
18342+ int type;
18343+ struct au_sbinfo *sbi = au_sbi(inode->i_sb);
18344+ const struct inode_operations *iop
18345+ = force_getattr ? aufs_iop : sbi->si_iop_array;
18346+
18347+ if (inode->i_op == iop)
18348+ return;
18349+
18350+ switch (inode->i_mode & S_IFMT) {
18351+ case S_IFDIR:
18352+ type = AuIop_DIR;
18353+ break;
18354+ case S_IFLNK:
18355+ type = AuIop_SYMLINK;
18356+ break;
18357+ default:
18358+ type = AuIop_OTHER;
18359+ break;
18360+ }
18361+
18362+ inode->i_op = iop + type;
18363+ /* unnecessary smp_wmb() */
18364+}
18365+
027c5e7a
AM
18366+int au_refresh_hinode_self(struct inode *inode)
18367+{
18368+ int err, update;
18369+
18370+ err = au_ii_refresh(inode, &update);
18371+ if (!err)
18372+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
18373+
18374+ AuTraceErr(err);
4a4d8108
AM
18375+ return err;
18376+}
1facf9fc 18377+
4a4d8108
AM
18378+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
18379+{
027c5e7a 18380+ int err, e, update;
4a4d8108 18381+ unsigned int flags;
027c5e7a 18382+ umode_t mode;
5afbbe0d 18383+ aufs_bindex_t bindex, bbot;
027c5e7a 18384+ unsigned char isdir;
4a4d8108
AM
18385+ struct au_hinode *p;
18386+ struct au_iinfo *iinfo;
1facf9fc 18387+
027c5e7a 18388+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
18389+ if (unlikely(err))
18390+ goto out;
18391+
18392+ update = 0;
18393+ iinfo = au_ii(inode);
5afbbe0d 18394+ p = au_hinode(iinfo, iinfo->ii_btop);
027c5e7a
AM
18395+ mode = (inode->i_mode & S_IFMT);
18396+ isdir = S_ISDIR(mode);
4a4d8108 18397+ flags = au_hi_flags(inode, isdir);
5afbbe0d
AM
18398+ bbot = au_dbbot(dentry);
18399+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
5527c038 18400+ struct inode *h_i, *h_inode;
4a4d8108
AM
18401+ struct dentry *h_d;
18402+
18403+ h_d = au_h_dptr(dentry, bindex);
5527c038 18404+ if (!h_d || d_is_negative(h_d))
4a4d8108
AM
18405+ continue;
18406+
5527c038
JR
18407+ h_inode = d_inode(h_d);
18408+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT));
5afbbe0d 18409+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) {
4a4d8108
AM
18410+ h_i = au_h_iptr(inode, bindex);
18411+ if (h_i) {
5527c038 18412+ if (h_i == h_inode)
4a4d8108
AM
18413+ continue;
18414+ err = -EIO;
18415+ break;
18416+ }
18417+ }
5afbbe0d
AM
18418+ if (bindex < iinfo->ii_btop)
18419+ iinfo->ii_btop = bindex;
18420+ if (iinfo->ii_bbot < bindex)
18421+ iinfo->ii_bbot = bindex;
5527c038 18422+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags);
4a4d8108 18423+ update = 1;
1308ab2a 18424+ }
4a4d8108
AM
18425+ au_update_ibrange(inode, /*do_put_zero*/0);
18426+ e = au_dy_irefresh(inode);
18427+ if (unlikely(e && !err))
18428+ err = e;
027c5e7a
AM
18429+ if (!err)
18430+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 18431+
4f0767ce 18432+out:
4a4d8108 18433+ AuTraceErr(err);
1308ab2a 18434+ return err;
dece6358
AM
18435+}
18436+
4a4d8108 18437+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 18438+{
4a4d8108
AM
18439+ int err;
18440+ unsigned int flags;
18441+ umode_t mode;
5afbbe0d 18442+ aufs_bindex_t bindex, btop, btail;
4a4d8108
AM
18443+ unsigned char isdir;
18444+ struct dentry *h_dentry;
18445+ struct inode *h_inode;
18446+ struct au_iinfo *iinfo;
b95c5147 18447+ struct inode_operations *iop;
dece6358 18448+
4a4d8108 18449+ IiMustWriteLock(inode);
dece6358 18450+
4a4d8108
AM
18451+ err = 0;
18452+ isdir = 0;
b95c5147 18453+ iop = au_sbi(inode->i_sb)->si_iop_array;
5afbbe0d
AM
18454+ btop = au_dbtop(dentry);
18455+ h_dentry = au_h_dptr(dentry, btop);
5527c038 18456+ h_inode = d_inode(h_dentry);
4a4d8108
AM
18457+ mode = h_inode->i_mode;
18458+ switch (mode & S_IFMT) {
18459+ case S_IFREG:
18460+ btail = au_dbtail(dentry);
b95c5147 18461+ inode->i_op = iop + AuIop_OTHER;
4a4d8108 18462+ inode->i_fop = &aufs_file_fop;
5afbbe0d 18463+ err = au_dy_iaop(inode, btop, h_inode);
4a4d8108
AM
18464+ if (unlikely(err))
18465+ goto out;
18466+ break;
18467+ case S_IFDIR:
18468+ isdir = 1;
18469+ btail = au_dbtaildir(dentry);
b95c5147 18470+ inode->i_op = iop + AuIop_DIR;
4a4d8108
AM
18471+ inode->i_fop = &aufs_dir_fop;
18472+ break;
18473+ case S_IFLNK:
18474+ btail = au_dbtail(dentry);
b95c5147 18475+ inode->i_op = iop + AuIop_SYMLINK;
4a4d8108
AM
18476+ break;
18477+ case S_IFBLK:
18478+ case S_IFCHR:
18479+ case S_IFIFO:
18480+ case S_IFSOCK:
18481+ btail = au_dbtail(dentry);
b95c5147 18482+ inode->i_op = iop + AuIop_OTHER;
38d290e6 18483+ init_special_inode(inode, mode, h_inode->i_rdev);
4a4d8108
AM
18484+ break;
18485+ default:
18486+ AuIOErr("Unknown file type 0%o\n", mode);
18487+ err = -EIO;
1308ab2a 18488+ goto out;
4a4d8108 18489+ }
dece6358 18490+
4a4d8108
AM
18491+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
18492+ flags = au_hi_flags(inode, isdir);
18493+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
18494+ && au_ftest_hi(flags, HNOTIFY)
18495+ && dentry->d_name.len > AUFS_WH_PFX_LEN
18496+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
18497+ au_fclr_hi(flags, HNOTIFY);
18498+ iinfo = au_ii(inode);
5afbbe0d
AM
18499+ iinfo->ii_btop = btop;
18500+ iinfo->ii_bbot = btail;
18501+ for (bindex = btop; bindex <= btail; bindex++) {
4a4d8108
AM
18502+ h_dentry = au_h_dptr(dentry, bindex);
18503+ if (h_dentry)
18504+ au_set_h_iptr(inode, bindex,
5527c038 18505+ au_igrab(d_inode(h_dentry)), flags);
4a4d8108
AM
18506+ }
18507+ au_cpup_attr_all(inode, /*force*/1);
c1595e42
JR
18508+ /*
18509+ * to force calling aufs_get_acl() every time,
18510+ * do not call cache_no_acl() for aufs inode.
18511+ */
dece6358 18512+
4f0767ce 18513+out:
4a4d8108
AM
18514+ return err;
18515+}
dece6358 18516+
027c5e7a
AM
18517+/*
18518+ * successful returns with iinfo write_locked
18519+ * minus: errno
18520+ * zero: success, matched
18521+ * plus: no error, but unmatched
18522+ */
18523+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
18524+{
18525+ int err;
cfc41e69 18526+ unsigned int gen, igflags;
5afbbe0d 18527+ aufs_bindex_t bindex, bbot;
4a4d8108 18528+ struct inode *h_inode, *h_dinode;
5527c038 18529+ struct dentry *h_dentry;
dece6358 18530+
4a4d8108
AM
18531+ /*
18532+ * before this function, if aufs got any iinfo lock, it must be only
18533+ * one, the parent dir.
18534+ * it can happen by UDBA and the obsoleted inode number.
18535+ */
18536+ err = -EIO;
18537+ if (unlikely(inode->i_ino == parent_ino(dentry)))
18538+ goto out;
18539+
027c5e7a 18540+ err = 1;
4a4d8108 18541+ ii_write_lock_new_child(inode);
5afbbe0d 18542+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry));
5527c038 18543+ h_dinode = d_inode(h_dentry);
5afbbe0d
AM
18544+ bbot = au_ibbot(inode);
18545+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108 18546+ h_inode = au_h_iptr(inode, bindex);
537831f9
AM
18547+ if (!h_inode || h_inode != h_dinode)
18548+ continue;
18549+
18550+ err = 0;
cfc41e69 18551+ gen = au_iigen(inode, &igflags);
537831f9 18552+ if (gen == au_digen(dentry)
cfc41e69 18553+ && !au_ig_ftest(igflags, HALF_REFRESHED))
4a4d8108 18554+ break;
537831f9
AM
18555+
18556+ /* fully refresh inode using dentry */
18557+ err = au_refresh_hinode(inode, dentry);
18558+ if (!err)
18559+ au_update_iigen(inode, /*half*/0);
18560+ break;
1facf9fc 18561+ }
dece6358 18562+
4a4d8108
AM
18563+ if (unlikely(err))
18564+ ii_write_unlock(inode);
4f0767ce 18565+out:
1facf9fc 18566+ return err;
18567+}
1facf9fc 18568+
4a4d8108
AM
18569+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18570+ unsigned int d_type, ino_t *ino)
1facf9fc 18571+{
521ced18
JR
18572+ int err, idx;
18573+ const int isnondir = d_type != DT_DIR;
1facf9fc 18574+
b752ccd1 18575+ /* prevent hardlinked inode number from race condition */
521ced18
JR
18576+ if (isnondir) {
18577+ err = au_xinondir_enter(sb, bindex, h_ino, &idx);
18578+ if (unlikely(err))
18579+ goto out;
4a4d8108 18580+ }
521ced18 18581+
4a4d8108
AM
18582+ err = au_xino_read(sb, bindex, h_ino, ino);
18583+ if (unlikely(err))
521ced18 18584+ goto out_xinondir;
1308ab2a 18585+
4a4d8108
AM
18586+ if (!*ino) {
18587+ err = -EIO;
18588+ *ino = au_xino_new_ino(sb);
18589+ if (unlikely(!*ino))
521ced18 18590+ goto out_xinondir;
4a4d8108
AM
18591+ err = au_xino_write(sb, bindex, h_ino, *ino);
18592+ if (unlikely(err))
521ced18 18593+ goto out_xinondir;
1308ab2a 18594+ }
1facf9fc 18595+
521ced18
JR
18596+out_xinondir:
18597+ if (isnondir && idx >= 0)
18598+ au_xinondir_leave(sb, bindex, h_ino, idx);
4f0767ce 18599+out:
1facf9fc 18600+ return err;
18601+}
18602+
4a4d8108
AM
18603+/* successful returns with iinfo write_locked */
18604+/* todo: return with unlocked? */
18605+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 18606+{
5527c038 18607+ struct inode *inode, *h_inode;
4a4d8108
AM
18608+ struct dentry *h_dentry;
18609+ struct super_block *sb;
18610+ ino_t h_ino, ino;
521ced18 18611+ int err, idx, hlinked;
5afbbe0d 18612+ aufs_bindex_t btop;
1facf9fc 18613+
4a4d8108 18614+ sb = dentry->d_sb;
5afbbe0d
AM
18615+ btop = au_dbtop(dentry);
18616+ h_dentry = au_h_dptr(dentry, btop);
5527c038
JR
18617+ h_inode = d_inode(h_dentry);
18618+ h_ino = h_inode->i_ino;
521ced18 18619+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1;
b752ccd1 18620+
521ced18 18621+new_ino:
b752ccd1
AM
18622+ /*
18623+ * stop 'race'-ing between hardlinks under different
18624+ * parents.
18625+ */
521ced18
JR
18626+ if (hlinked) {
18627+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18628+ inode = ERR_PTR(err);
18629+ if (unlikely(err))
18630+ goto out;
18631+ }
b752ccd1 18632+
5afbbe0d 18633+ err = au_xino_read(sb, btop, h_ino, &ino);
4a4d8108
AM
18634+ inode = ERR_PTR(err);
18635+ if (unlikely(err))
521ced18 18636+ goto out_xinondir;
b752ccd1 18637+
4a4d8108
AM
18638+ if (!ino) {
18639+ ino = au_xino_new_ino(sb);
18640+ if (unlikely(!ino)) {
18641+ inode = ERR_PTR(-EIO);
521ced18 18642+ goto out_xinondir;
dece6358
AM
18643+ }
18644+ }
1facf9fc 18645+
4a4d8108
AM
18646+ AuDbg("i%lu\n", (unsigned long)ino);
18647+ inode = au_iget_locked(sb, ino);
18648+ err = PTR_ERR(inode);
18649+ if (IS_ERR(inode))
521ced18 18650+ goto out_xinondir;
1facf9fc 18651+
4a4d8108
AM
18652+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
18653+ if (inode->i_state & I_NEW) {
18654+ ii_write_lock_new_child(inode);
18655+ err = set_inode(inode, dentry);
18656+ if (!err) {
18657+ unlock_new_inode(inode);
521ced18 18658+ goto out_xinondir; /* success */
4a4d8108 18659+ }
1308ab2a 18660+
027c5e7a
AM
18661+ /*
18662+ * iget_failed() calls iput(), but we need to call
18663+ * ii_write_unlock() after iget_failed(). so dirty hack for
18664+ * i_count.
18665+ */
18666+ atomic_inc(&inode->i_count);
4a4d8108 18667+ iget_failed(inode);
027c5e7a 18668+ ii_write_unlock(inode);
5afbbe0d 18669+ au_xino_write(sb, btop, h_ino, /*ino*/0);
027c5e7a
AM
18670+ /* ignore this error */
18671+ goto out_iput;
18672+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
18673+ /*
18674+ * horrible race condition between lookup, readdir and copyup
18675+ * (or something).
18676+ */
521ced18
JR
18677+ if (hlinked && idx >= 0)
18678+ au_xinondir_leave(sb, btop, h_ino, idx);
027c5e7a
AM
18679+ err = reval_inode(inode, dentry);
18680+ if (unlikely(err < 0)) {
521ced18 18681+ hlinked = 0;
027c5e7a
AM
18682+ goto out_iput;
18683+ }
521ced18 18684+ if (!err)
4a4d8108 18685+ goto out; /* success */
521ced18
JR
18686+ else if (hlinked && idx >= 0) {
18687+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18688+ if (unlikely(err)) {
18689+ iput(inode);
18690+ inode = ERR_PTR(err);
18691+ goto out;
18692+ }
18693+ }
4a4d8108
AM
18694+ }
18695+
5527c038 18696+ if (unlikely(au_test_fs_unique_ino(h_inode)))
4a4d8108 18697+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
523b37e3 18698+ " b%d, %s, %pd, hi%lu, i%lu.\n",
5afbbe0d 18699+ btop, au_sbtype(h_dentry->d_sb), dentry,
4a4d8108
AM
18700+ (unsigned long)h_ino, (unsigned long)ino);
18701+ ino = 0;
5afbbe0d 18702+ err = au_xino_write(sb, btop, h_ino, /*ino*/0);
4a4d8108
AM
18703+ if (!err) {
18704+ iput(inode);
521ced18
JR
18705+ if (hlinked && idx >= 0)
18706+ au_xinondir_leave(sb, btop, h_ino, idx);
4a4d8108
AM
18707+ goto new_ino;
18708+ }
1308ab2a 18709+
4f0767ce 18710+out_iput:
4a4d8108 18711+ iput(inode);
4a4d8108 18712+ inode = ERR_PTR(err);
521ced18
JR
18713+out_xinondir:
18714+ if (hlinked && idx >= 0)
18715+ au_xinondir_leave(sb, btop, h_ino, idx);
4f0767ce 18716+out:
4a4d8108 18717+ return inode;
1facf9fc 18718+}
18719+
4a4d8108 18720+/* ---------------------------------------------------------------------- */
1facf9fc 18721+
4a4d8108
AM
18722+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18723+ struct inode *inode)
18724+{
18725+ int err;
076b876e 18726+ struct inode *hi;
1facf9fc 18727+
4a4d8108 18728+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 18729+
4a4d8108
AM
18730+ /* pseudo-link after flushed may happen out of bounds */
18731+ if (!err
18732+ && inode
5afbbe0d
AM
18733+ && au_ibtop(inode) <= bindex
18734+ && bindex <= au_ibbot(inode)) {
4a4d8108
AM
18735+ /*
18736+ * permission check is unnecessary since vfsub routine
18737+ * will be called later
18738+ */
076b876e 18739+ hi = au_h_iptr(inode, bindex);
4a4d8108
AM
18740+ if (hi)
18741+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 18742+ }
18743+
4a4d8108
AM
18744+ return err;
18745+}
dece6358 18746+
4a4d8108
AM
18747+int au_test_h_perm(struct inode *h_inode, int mask)
18748+{
2dfbb274 18749+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
4a4d8108
AM
18750+ return 0;
18751+ return inode_permission(h_inode, mask);
18752+}
1facf9fc 18753+
4a4d8108
AM
18754+int au_test_h_perm_sio(struct inode *h_inode, int mask)
18755+{
18756+ if (au_test_nfs(h_inode->i_sb)
18757+ && (mask & MAY_WRITE)
18758+ && S_ISDIR(h_inode->i_mode))
18759+ mask |= MAY_READ; /* force permission check */
18760+ return au_test_h_perm(h_inode, mask);
1facf9fc 18761+}
7f207e10 18762diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
fbc438ed
JR
18763--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 08:00:00.000000000 +0800
18764+++ linux/fs/aufs/inode.h 2019-07-11 21:21:54.382384486 +0800
9f237c51 18765@@ -0,0 +1,698 @@
062440b3 18766+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 18767+/*
ba1aed25 18768+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
18769+ *
18770+ * This program, aufs is free software; you can redistribute it and/or modify
18771+ * it under the terms of the GNU General Public License as published by
18772+ * the Free Software Foundation; either version 2 of the License, or
18773+ * (at your option) any later version.
18774+ *
18775+ * This program is distributed in the hope that it will be useful,
18776+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18777+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18778+ * GNU General Public License for more details.
18779+ *
18780+ * You should have received a copy of the GNU General Public License
523b37e3 18781+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18782+ */
1facf9fc 18783+
1308ab2a 18784+/*
4a4d8108 18785+ * inode operations
1308ab2a 18786+ */
dece6358 18787+
4a4d8108
AM
18788+#ifndef __AUFS_INODE_H__
18789+#define __AUFS_INODE_H__
dece6358 18790+
4a4d8108 18791+#ifdef __KERNEL__
1308ab2a 18792+
4a4d8108 18793+#include <linux/fsnotify.h>
4a4d8108 18794+#include "rwsem.h"
1308ab2a 18795+
4a4d8108 18796+struct vfsmount;
1facf9fc 18797+
4a4d8108
AM
18798+struct au_hnotify {
18799+#ifdef CONFIG_AUFS_HNOTIFY
18800+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 18801+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 18802+ struct fsnotify_mark hn_mark;
4a4d8108 18803+#endif
1c60b727 18804+ struct inode *hn_aufs_inode; /* no get/put */
9f237c51 18805+ struct rcu_head rcu;
4a4d8108
AM
18806+#endif
18807+} ____cacheline_aligned_in_smp;
1facf9fc 18808+
4a4d8108
AM
18809+struct au_hinode {
18810+ struct inode *hi_inode;
18811+ aufs_bindex_t hi_id;
18812+#ifdef CONFIG_AUFS_HNOTIFY
18813+ struct au_hnotify *hi_notify;
18814+#endif
dece6358 18815+
4a4d8108
AM
18816+ /* reference to the copied-up whiteout with get/put */
18817+ struct dentry *hi_whdentry;
18818+};
dece6358 18819+
537831f9
AM
18820+/* ig_flags */
18821+#define AuIG_HALF_REFRESHED 1
18822+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name)
18823+#define au_ig_fset(flags, name) \
18824+ do { (flags) |= AuIG_##name; } while (0)
18825+#define au_ig_fclr(flags, name) \
18826+ do { (flags) &= ~AuIG_##name; } while (0)
18827+
18828+struct au_iigen {
be52b249 18829+ spinlock_t ig_spin;
537831f9
AM
18830+ __u32 ig_generation, ig_flags;
18831+};
18832+
4a4d8108
AM
18833+struct au_vdir;
18834+struct au_iinfo {
7a9e40b8 18835+ struct au_iigen ii_generation;
4a4d8108 18836+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 18837+
4a4d8108 18838+ struct au_rwsem ii_rwsem;
5afbbe0d 18839+ aufs_bindex_t ii_btop, ii_bbot;
4a4d8108
AM
18840+ __u32 ii_higen;
18841+ struct au_hinode *ii_hinode;
18842+ struct au_vdir *ii_vdir;
18843+};
1facf9fc 18844+
4a4d8108 18845+struct au_icntnr {
9f237c51
AM
18846+ struct au_iinfo iinfo;
18847+ struct inode vfs_inode;
18848+ struct hlist_bl_node plink;
18849+ struct rcu_head rcu;
4a4d8108 18850+} ____cacheline_aligned_in_smp;
1308ab2a 18851+
4a4d8108
AM
18852+/* au_pin flags */
18853+#define AuPin_DI_LOCKED 1
18854+#define AuPin_MNT_WRITE (1 << 1)
18855+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
18856+#define au_fset_pin(flags, name) \
18857+ do { (flags) |= AuPin_##name; } while (0)
18858+#define au_fclr_pin(flags, name) \
18859+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
18860+
18861+struct au_pin {
18862+ /* input */
18863+ struct dentry *dentry;
18864+ unsigned int udba;
18865+ unsigned char lsc_di, lsc_hi, flags;
18866+ aufs_bindex_t bindex;
18867+
18868+ /* output */
18869+ struct dentry *parent;
18870+ struct au_hinode *hdir;
18871+ struct vfsmount *h_mnt;
86dc4139
AM
18872+
18873+ /* temporary unlock/relock for copyup */
18874+ struct dentry *h_dentry, *h_parent;
18875+ struct au_branch *br;
18876+ struct task_struct *task;
4a4d8108 18877+};
1facf9fc 18878+
86dc4139 18879+void au_pin_hdir_unlock(struct au_pin *p);
c1595e42 18880+int au_pin_hdir_lock(struct au_pin *p);
86dc4139 18881+int au_pin_hdir_relock(struct au_pin *p);
86dc4139
AM
18882+void au_pin_hdir_acquire_nest(struct au_pin *p);
18883+void au_pin_hdir_release(struct au_pin *p);
18884+
1308ab2a 18885+/* ---------------------------------------------------------------------- */
18886+
4a4d8108 18887+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 18888+{
5afbbe0d
AM
18889+ BUG_ON(is_bad_inode(inode));
18890+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
4a4d8108 18891+}
1facf9fc 18892+
4a4d8108 18893+/* ---------------------------------------------------------------------- */
1facf9fc 18894+
4a4d8108
AM
18895+/* inode.c */
18896+struct inode *au_igrab(struct inode *inode);
b95c5147 18897+void au_refresh_iop(struct inode *inode, int force_getattr);
027c5e7a 18898+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
18899+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
18900+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18901+ unsigned int d_type, ino_t *ino);
18902+struct inode *au_new_inode(struct dentry *dentry, int must_new);
18903+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18904+ struct inode *inode);
18905+int au_test_h_perm(struct inode *h_inode, int mask);
18906+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 18907+
4a4d8108
AM
18908+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
18909+ ino_t h_ino, unsigned int d_type, ino_t *ino)
18910+{
18911+#ifdef CONFIG_AUFS_SHWH
18912+ return au_ino(sb, bindex, h_ino, d_type, ino);
18913+#else
18914+ return 0;
18915+#endif
18916+}
1facf9fc 18917+
4a4d8108 18918+/* i_op.c */
b95c5147
AM
18919+enum {
18920+ AuIop_SYMLINK,
18921+ AuIop_DIR,
18922+ AuIop_OTHER,
18923+ AuIop_Last
18924+};
18925+extern struct inode_operations aufs_iop[AuIop_Last],
18926+ aufs_iop_nogetattr[AuIop_Last];
1308ab2a 18927+
4a4d8108
AM
18928+/* au_wr_dir flags */
18929+#define AuWrDir_ADD_ENTRY 1
7e9cd9fe
AM
18930+#define AuWrDir_ISDIR (1 << 1)
18931+#define AuWrDir_TMPFILE (1 << 2)
4a4d8108 18932+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
18933+#define au_fset_wrdir(flags, name) \
18934+ do { (flags) |= AuWrDir_##name; } while (0)
18935+#define au_fclr_wrdir(flags, name) \
18936+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 18937+
4a4d8108
AM
18938+struct au_wr_dir_args {
18939+ aufs_bindex_t force_btgt;
18940+ unsigned char flags;
18941+};
18942+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
18943+ struct au_wr_dir_args *args);
dece6358 18944+
4a4d8108
AM
18945+struct dentry *au_pinned_h_parent(struct au_pin *pin);
18946+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
18947+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
18948+ unsigned int udba, unsigned char flags);
18949+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
18950+ unsigned int udba, unsigned char flags) __must_check;
18951+int au_do_pin(struct au_pin *pin) __must_check;
18952+void au_unpin(struct au_pin *pin);
c1595e42
JR
18953+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen);
18954+
18955+#define AuIcpup_DID_CPUP 1
18956+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
18957+#define au_fset_icpup(flags, name) \
18958+ do { (flags) |= AuIcpup_##name; } while (0)
18959+#define au_fclr_icpup(flags, name) \
18960+ do { (flags) &= ~AuIcpup_##name; } while (0)
18961+
18962+struct au_icpup_args {
18963+ unsigned char flags;
18964+ unsigned char pin_flags;
18965+ aufs_bindex_t btgt;
18966+ unsigned int udba;
18967+ struct au_pin pin;
18968+ struct path h_path;
18969+ struct inode *h_inode;
18970+};
18971+
18972+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
18973+ struct au_icpup_args *a);
18974+
a2654f78
AM
18975+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
18976+ int locked);
1facf9fc 18977+
4a4d8108
AM
18978+/* i_op_add.c */
18979+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
18980+ struct dentry *h_parent, int isdir);
7eafdf33
AM
18981+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
18982+ dev_t dev);
4a4d8108 18983+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
7eafdf33 18984+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 18985+ bool want_excl);
b912730e
AM
18986+struct vfsub_aopen_args;
18987+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
18988+ struct vfsub_aopen_args *args);
38d290e6 18989+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode);
4a4d8108
AM
18990+int aufs_link(struct dentry *src_dentry, struct inode *dir,
18991+ struct dentry *dentry);
7eafdf33 18992+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
1facf9fc 18993+
4a4d8108
AM
18994+/* i_op_del.c */
18995+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
18996+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
18997+ struct dentry *h_parent, int isdir);
18998+int aufs_unlink(struct inode *dir, struct dentry *dentry);
18999+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 19000+
4a4d8108
AM
19001+/* i_op_ren.c */
19002+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
19003+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
f2c43d5f
AM
19004+ struct inode *dir, struct dentry *dentry,
19005+ unsigned int flags);
1facf9fc 19006+
4a4d8108
AM
19007+/* iinfo.c */
19008+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
19009+void au_hiput(struct au_hinode *hinode);
19010+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
19011+ struct dentry *h_wh);
19012+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 19013+
4a4d8108
AM
19014+/* hinode flags */
19015+#define AuHi_XINO 1
19016+#define AuHi_HNOTIFY (1 << 1)
19017+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
19018+#define au_fset_hi(flags, name) \
19019+ do { (flags) |= AuHi_##name; } while (0)
19020+#define au_fclr_hi(flags, name) \
19021+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 19022+
4a4d8108
AM
19023+#ifndef CONFIG_AUFS_HNOTIFY
19024+#undef AuHi_HNOTIFY
19025+#define AuHi_HNOTIFY 0
19026+#endif
1facf9fc 19027+
4a4d8108
AM
19028+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
19029+ struct inode *h_inode, unsigned int flags);
1facf9fc 19030+
537831f9 19031+void au_update_iigen(struct inode *inode, int half);
4a4d8108 19032+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 19033+
4a4d8108 19034+void au_icntnr_init_once(void *_c);
5afbbe0d 19035+void au_hinode_init(struct au_hinode *hinode);
4a4d8108
AM
19036+int au_iinfo_init(struct inode *inode);
19037+void au_iinfo_fin(struct inode *inode);
e2f27e51 19038+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink);
1308ab2a 19039+
e49829fe 19040+#ifdef CONFIG_PROC_FS
4a4d8108 19041+/* plink.c */
e49829fe 19042+int au_plink_maint(struct super_block *sb, int flags);
7e9cd9fe 19043+struct au_sbinfo;
e49829fe
JR
19044+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
19045+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
19046+#ifdef CONFIG_AUFS_DEBUG
19047+void au_plink_list(struct super_block *sb);
19048+#else
19049+AuStubVoid(au_plink_list, struct super_block *sb)
19050+#endif
19051+int au_plink_test(struct inode *inode);
19052+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
19053+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
19054+ struct dentry *h_dentry);
e49829fe
JR
19055+void au_plink_put(struct super_block *sb, int verbose);
19056+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 19057+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
19058+#else
19059+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
19060+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
19061+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
19062+AuStubVoid(au_plink_list, struct super_block *sb);
19063+AuStubInt0(au_plink_test, struct inode *inode);
19064+AuStub(struct dentry *, au_plink_lkup, return NULL,
19065+ struct inode *inode, aufs_bindex_t bindex);
19066+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
19067+ struct dentry *h_dentry);
19068+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
19069+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
19070+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
19071+#endif /* CONFIG_PROC_FS */
1facf9fc 19072+
c1595e42
JR
19073+#ifdef CONFIG_AUFS_XATTR
19074+/* xattr.c */
7e9cd9fe
AM
19075+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
19076+ unsigned int verbose);
c1595e42 19077+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size);
f2c43d5f 19078+void au_xattr_init(struct super_block *sb);
c1595e42
JR
19079+#else
19080+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src,
7e9cd9fe 19081+ int ignore_flags, unsigned int verbose);
f2c43d5f 19082+AuStubVoid(au_xattr_init, struct super_block *sb);
c1595e42
JR
19083+#endif
19084+
19085+#ifdef CONFIG_FS_POSIX_ACL
19086+struct posix_acl *aufs_get_acl(struct inode *inode, int type);
19087+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
19088+#endif
19089+
19090+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
19091+enum {
19092+ AU_XATTR_SET,
c1595e42
JR
19093+ AU_ACL_SET
19094+};
19095+
f2c43d5f 19096+struct au_sxattr {
c1595e42
JR
19097+ int type;
19098+ union {
19099+ struct {
19100+ const char *name;
19101+ const void *value;
19102+ size_t size;
19103+ int flags;
19104+ } set;
19105+ struct {
c1595e42
JR
19106+ struct posix_acl *acl;
19107+ int type;
19108+ } acl_set;
19109+ } u;
19110+};
f2c43d5f
AM
19111+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
19112+ struct au_sxattr *arg);
c1595e42
JR
19113+#endif
19114+
4a4d8108 19115+/* ---------------------------------------------------------------------- */
1308ab2a 19116+
4a4d8108
AM
19117+/* lock subclass for iinfo */
19118+enum {
19119+ AuLsc_II_CHILD, /* child first */
19120+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
19121+ AuLsc_II_CHILD3, /* copyup dirs */
19122+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
19123+ AuLsc_II_PARENT2,
19124+ AuLsc_II_PARENT3, /* copyup dirs */
19125+ AuLsc_II_NEW_CHILD
19126+};
1308ab2a 19127+
1facf9fc 19128+/*
4a4d8108
AM
19129+ * ii_read_lock_child, ii_write_lock_child,
19130+ * ii_read_lock_child2, ii_write_lock_child2,
19131+ * ii_read_lock_child3, ii_write_lock_child3,
19132+ * ii_read_lock_parent, ii_write_lock_parent,
19133+ * ii_read_lock_parent2, ii_write_lock_parent2,
19134+ * ii_read_lock_parent3, ii_write_lock_parent3,
19135+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 19136+ */
4a4d8108
AM
19137+#define AuReadLockFunc(name, lsc) \
19138+static inline void ii_read_lock_##name(struct inode *i) \
19139+{ \
19140+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
19141+}
19142+
19143+#define AuWriteLockFunc(name, lsc) \
19144+static inline void ii_write_lock_##name(struct inode *i) \
19145+{ \
19146+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
19147+}
19148+
19149+#define AuRWLockFuncs(name, lsc) \
19150+ AuReadLockFunc(name, lsc) \
19151+ AuWriteLockFunc(name, lsc)
19152+
19153+AuRWLockFuncs(child, CHILD);
19154+AuRWLockFuncs(child2, CHILD2);
19155+AuRWLockFuncs(child3, CHILD3);
19156+AuRWLockFuncs(parent, PARENT);
19157+AuRWLockFuncs(parent2, PARENT2);
19158+AuRWLockFuncs(parent3, PARENT3);
19159+AuRWLockFuncs(new_child, NEW_CHILD);
19160+
19161+#undef AuReadLockFunc
19162+#undef AuWriteLockFunc
19163+#undef AuRWLockFuncs
1facf9fc 19164+
8b6a4947
AM
19165+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem)
19166+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem)
19167+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem)
1facf9fc 19168+
4a4d8108
AM
19169+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
19170+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
19171+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 19172+
4a4d8108 19173+/* ---------------------------------------------------------------------- */
1308ab2a 19174+
027c5e7a
AM
19175+static inline void au_icntnr_init(struct au_icntnr *c)
19176+{
19177+#ifdef CONFIG_AUFS_DEBUG
19178+ c->vfs_inode.i_mode = 0;
19179+#endif
19180+}
19181+
cfc41e69 19182+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags)
4a4d8108 19183+{
537831f9
AM
19184+ unsigned int gen;
19185+ struct au_iinfo *iinfo;
be52b249 19186+ struct au_iigen *iigen;
537831f9
AM
19187+
19188+ iinfo = au_ii(inode);
be52b249
AM
19189+ iigen = &iinfo->ii_generation;
19190+ spin_lock(&iigen->ig_spin);
cfc41e69
AM
19191+ if (igflags)
19192+ *igflags = iigen->ig_flags;
be52b249
AM
19193+ gen = iigen->ig_generation;
19194+ spin_unlock(&iigen->ig_spin);
537831f9
AM
19195+
19196+ return gen;
4a4d8108 19197+}
1308ab2a 19198+
4a4d8108
AM
19199+/* tiny test for inode number */
19200+/* tmpfs generation is too rough */
19201+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
19202+{
19203+ struct au_iinfo *iinfo;
1308ab2a 19204+
4a4d8108
AM
19205+ iinfo = au_ii(inode);
19206+ AuRwMustAnyLock(&iinfo->ii_rwsem);
19207+ return !(iinfo->ii_hsb1 == h_inode->i_sb
19208+ && iinfo->ii_higen == h_inode->i_generation);
19209+}
1308ab2a 19210+
4a4d8108
AM
19211+static inline void au_iigen_dec(struct inode *inode)
19212+{
537831f9 19213+ struct au_iinfo *iinfo;
be52b249 19214+ struct au_iigen *iigen;
537831f9
AM
19215+
19216+ iinfo = au_ii(inode);
be52b249
AM
19217+ iigen = &iinfo->ii_generation;
19218+ spin_lock(&iigen->ig_spin);
19219+ iigen->ig_generation--;
19220+ spin_unlock(&iigen->ig_spin);
027c5e7a
AM
19221+}
19222+
19223+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
19224+{
19225+ int err;
19226+
19227+ err = 0;
537831f9 19228+ if (unlikely(inode && au_iigen(inode, NULL) != sigen))
027c5e7a
AM
19229+ err = -EIO;
19230+
19231+ return err;
4a4d8108 19232+}
1308ab2a 19233+
4a4d8108 19234+/* ---------------------------------------------------------------------- */
1308ab2a 19235+
5afbbe0d
AM
19236+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo,
19237+ aufs_bindex_t bindex)
19238+{
19239+ return iinfo->ii_hinode + bindex;
19240+}
19241+
19242+static inline int au_is_bad_inode(struct inode *inode)
19243+{
19244+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0));
19245+}
19246+
4a4d8108
AM
19247+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
19248+ aufs_bindex_t bindex)
19249+{
19250+ IiMustAnyLock(inode);
5afbbe0d 19251+ return au_hinode(au_ii(inode), bindex)->hi_id;
4a4d8108 19252+}
1308ab2a 19253+
5afbbe0d 19254+static inline aufs_bindex_t au_ibtop(struct inode *inode)
4a4d8108
AM
19255+{
19256+ IiMustAnyLock(inode);
5afbbe0d 19257+ return au_ii(inode)->ii_btop;
4a4d8108 19258+}
1308ab2a 19259+
5afbbe0d 19260+static inline aufs_bindex_t au_ibbot(struct inode *inode)
4a4d8108
AM
19261+{
19262+ IiMustAnyLock(inode);
5afbbe0d 19263+ return au_ii(inode)->ii_bbot;
4a4d8108 19264+}
1308ab2a 19265+
4a4d8108
AM
19266+static inline struct au_vdir *au_ivdir(struct inode *inode)
19267+{
19268+ IiMustAnyLock(inode);
19269+ return au_ii(inode)->ii_vdir;
19270+}
1308ab2a 19271+
4a4d8108
AM
19272+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
19273+{
19274+ IiMustAnyLock(inode);
5afbbe0d 19275+ return au_hinode(au_ii(inode), bindex)->hi_whdentry;
4a4d8108 19276+}
1308ab2a 19277+
5afbbe0d 19278+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19279+{
4a4d8108 19280+ IiMustWriteLock(inode);
5afbbe0d 19281+ au_ii(inode)->ii_btop = bindex;
4a4d8108 19282+}
1308ab2a 19283+
5afbbe0d 19284+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex)
4a4d8108
AM
19285+{
19286+ IiMustWriteLock(inode);
5afbbe0d 19287+ au_ii(inode)->ii_bbot = bindex;
1308ab2a 19288+}
19289+
4a4d8108
AM
19290+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
19291+{
19292+ IiMustWriteLock(inode);
19293+ au_ii(inode)->ii_vdir = vdir;
19294+}
1facf9fc 19295+
4a4d8108 19296+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19297+{
4a4d8108 19298+ IiMustAnyLock(inode);
5afbbe0d 19299+ return au_hinode(au_ii(inode), bindex);
4a4d8108 19300+}
dece6358 19301+
4a4d8108 19302+/* ---------------------------------------------------------------------- */
1facf9fc 19303+
4a4d8108
AM
19304+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
19305+{
19306+ if (pin)
19307+ return pin->parent;
19308+ return NULL;
1facf9fc 19309+}
19310+
4a4d8108 19311+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 19312+{
4a4d8108
AM
19313+ if (pin && pin->hdir)
19314+ return pin->hdir->hi_inode;
19315+ return NULL;
1308ab2a 19316+}
1facf9fc 19317+
4a4d8108
AM
19318+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
19319+{
19320+ if (pin)
19321+ return pin->hdir;
19322+ return NULL;
19323+}
1facf9fc 19324+
4a4d8108 19325+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 19326+{
4a4d8108
AM
19327+ if (pin)
19328+ pin->dentry = dentry;
19329+}
1308ab2a 19330+
4a4d8108
AM
19331+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
19332+ unsigned char lflag)
19333+{
19334+ if (pin) {
7f207e10 19335+ if (lflag)
4a4d8108 19336+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 19337+ else
4a4d8108 19338+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 19339+ }
4a4d8108
AM
19340+}
19341+
7e9cd9fe 19342+#if 0 /* reserved */
4a4d8108
AM
19343+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
19344+{
19345+ if (pin) {
19346+ dput(pin->parent);
19347+ pin->parent = dget(parent);
1facf9fc 19348+ }
4a4d8108 19349+}
7e9cd9fe 19350+#endif
1facf9fc 19351+
4a4d8108
AM
19352+/* ---------------------------------------------------------------------- */
19353+
027c5e7a 19354+struct au_branch;
4a4d8108
AM
19355+#ifdef CONFIG_AUFS_HNOTIFY
19356+struct au_hnotify_op {
19357+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 19358+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
19359+
19360+ /*
19361+ * if it returns true, the the caller should free hinode->hi_notify,
19362+ * otherwise ->free() frees it.
19363+ */
19364+ int (*free)(struct au_hinode *hinode,
19365+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
19366+
19367+ void (*fin)(void);
19368+ int (*init)(void);
027c5e7a
AM
19369+
19370+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
19371+ void (*fin_br)(struct au_branch *br);
19372+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
19373+};
19374+
19375+/* hnotify.c */
027c5e7a 19376+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
19377+void au_hn_free(struct au_hinode *hinode);
19378+void au_hn_ctl(struct au_hinode *hinode, int do_set);
19379+void au_hn_reset(struct inode *inode, unsigned int flags);
19380+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
fbc438ed 19381+ const struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
19382+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
19383+int au_hnotify_init_br(struct au_branch *br, int perm);
19384+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
19385+int __init au_hnotify_init(void);
19386+void au_hnotify_fin(void);
19387+
7f207e10 19388+/* hfsnotify.c */
4a4d8108
AM
19389+extern const struct au_hnotify_op au_hnotify_op;
19390+
19391+static inline
19392+void au_hn_init(struct au_hinode *hinode)
19393+{
19394+ hinode->hi_notify = NULL;
1308ab2a 19395+}
19396+
53392da6
AM
19397+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
19398+{
19399+ return hinode->hi_notify;
19400+}
19401+
4a4d8108 19402+#else
c1595e42
JR
19403+AuStub(int, au_hn_alloc, return -EOPNOTSUPP,
19404+ struct au_hinode *hinode __maybe_unused,
19405+ struct inode *inode __maybe_unused)
19406+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode)
4a4d8108
AM
19407+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
19408+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
19409+ int do_set __maybe_unused)
19410+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
19411+ unsigned int flags __maybe_unused)
027c5e7a
AM
19412+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
19413+ struct au_branch *br __maybe_unused,
19414+ int perm __maybe_unused)
19415+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
19416+ int perm __maybe_unused)
19417+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
19418+AuStubInt0(__init au_hnotify_init, void)
19419+AuStubVoid(au_hnotify_fin, void)
19420+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
19421+#endif /* CONFIG_AUFS_HNOTIFY */
19422+
19423+static inline void au_hn_suspend(struct au_hinode *hdir)
19424+{
19425+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 19426+}
19427+
4a4d8108 19428+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 19429+{
4a4d8108
AM
19430+ au_hn_ctl(hdir, /*do_set*/1);
19431+}
1308ab2a 19432+
5afbbe0d 19433+static inline void au_hn_inode_lock(struct au_hinode *hdir)
4a4d8108 19434+{
febd17d6 19435+ inode_lock(hdir->hi_inode);
4a4d8108
AM
19436+ au_hn_suspend(hdir);
19437+}
dece6358 19438+
5afbbe0d 19439+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir,
4a4d8108
AM
19440+ unsigned int sc __maybe_unused)
19441+{
febd17d6 19442+ inode_lock_nested(hdir->hi_inode, sc);
4a4d8108 19443+ au_hn_suspend(hdir);
1facf9fc 19444+}
1facf9fc 19445+
8b6a4947
AM
19446+#if 0 /* unused */
19447+#include "vfsub.h"
3c1bdaff
AM
19448+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir,
19449+ unsigned int sc)
19450+{
be118d29 19451+ inode_lock_shared_nested(hdir->hi_inode, sc);
3c1bdaff
AM
19452+ au_hn_suspend(hdir);
19453+}
8b6a4947 19454+#endif
3c1bdaff 19455+
5afbbe0d 19456+static inline void au_hn_inode_unlock(struct au_hinode *hdir)
4a4d8108
AM
19457+{
19458+ au_hn_resume(hdir);
febd17d6 19459+ inode_unlock(hdir->hi_inode);
4a4d8108
AM
19460+}
19461+
19462+#endif /* __KERNEL__ */
19463+#endif /* __AUFS_INODE_H__ */
7f207e10 19464diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
fbc438ed
JR
19465--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 08:00:00.000000000 +0800
19466+++ linux/fs/aufs/ioctl.c 2019-07-11 21:21:54.382384486 +0800
062440b3 19467@@ -0,0 +1,220 @@
cd7a4cd9 19468+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19469+/*
ba1aed25 19470+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
19471+ *
19472+ * This program, aufs is free software; you can redistribute it and/or modify
19473+ * it under the terms of the GNU General Public License as published by
19474+ * the Free Software Foundation; either version 2 of the License, or
19475+ * (at your option) any later version.
19476+ *
19477+ * This program is distributed in the hope that it will be useful,
19478+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19479+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19480+ * GNU General Public License for more details.
19481+ *
19482+ * You should have received a copy of the GNU General Public License
523b37e3 19483+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19484+ */
19485+
19486+/*
19487+ * ioctl
19488+ * plink-management and readdir in userspace.
19489+ * assist the pathconf(3) wrapper library.
c2b27bf2 19490+ * move-down
076b876e 19491+ * File-based Hierarchical Storage Management.
4a4d8108
AM
19492+ */
19493+
c2b27bf2
AM
19494+#include <linux/compat.h>
19495+#include <linux/file.h>
4a4d8108
AM
19496+#include "aufs.h"
19497+
1e00d052 19498+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
19499+{
19500+ int err, fd;
5afbbe0d 19501+ aufs_bindex_t wbi, bindex, bbot;
4a4d8108
AM
19502+ struct file *h_file;
19503+ struct super_block *sb;
19504+ struct dentry *root;
1e00d052
AM
19505+ struct au_branch *br;
19506+ struct aufs_wbr_fd wbrfd = {
19507+ .oflags = au_dir_roflags,
19508+ .brid = -1
19509+ };
19510+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
19511+ | O_NOATIME | O_CLOEXEC;
4a4d8108 19512+
1e00d052
AM
19513+ AuDebugOn(wbrfd.oflags & ~valid);
19514+
19515+ if (arg) {
19516+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
19517+ if (unlikely(err)) {
19518+ err = -EFAULT;
19519+ goto out;
19520+ }
19521+
19522+ err = -EINVAL;
19523+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
19524+ wbrfd.oflags |= au_dir_roflags;
19525+ AuDbg("0%o\n", wbrfd.oflags);
19526+ if (unlikely(wbrfd.oflags & ~valid))
19527+ goto out;
19528+ }
19529+
2000de60 19530+ fd = get_unused_fd_flags(0);
1e00d052
AM
19531+ err = fd;
19532+ if (unlikely(fd < 0))
4a4d8108 19533+ goto out;
4a4d8108 19534+
1e00d052 19535+ h_file = ERR_PTR(-EINVAL);
4a4d8108 19536+ wbi = 0;
1e00d052 19537+ br = NULL;
4a4d8108
AM
19538+ sb = path->dentry->d_sb;
19539+ root = sb->s_root;
19540+ aufs_read_lock(root, AuLock_IR);
5afbbe0d 19541+ bbot = au_sbbot(sb);
1e00d052
AM
19542+ if (wbrfd.brid >= 0) {
19543+ wbi = au_br_index(sb, wbrfd.brid);
5afbbe0d 19544+ if (unlikely(wbi < 0 || wbi > bbot))
1e00d052
AM
19545+ goto out_unlock;
19546+ }
19547+
19548+ h_file = ERR_PTR(-ENOENT);
19549+ br = au_sbr(sb, wbi);
19550+ if (!au_br_writable(br->br_perm)) {
19551+ if (arg)
19552+ goto out_unlock;
19553+
19554+ bindex = wbi + 1;
19555+ wbi = -1;
5afbbe0d 19556+ for (; bindex <= bbot; bindex++) {
1e00d052
AM
19557+ br = au_sbr(sb, bindex);
19558+ if (au_br_writable(br->br_perm)) {
4a4d8108 19559+ wbi = bindex;
1e00d052 19560+ br = au_sbr(sb, wbi);
4a4d8108
AM
19561+ break;
19562+ }
19563+ }
4a4d8108
AM
19564+ }
19565+ AuDbg("wbi %d\n", wbi);
1e00d052 19566+ if (wbi >= 0)
392086de
AM
19567+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL,
19568+ /*force_wr*/0);
1e00d052
AM
19569+
19570+out_unlock:
4a4d8108
AM
19571+ aufs_read_unlock(root, AuLock_IR);
19572+ err = PTR_ERR(h_file);
19573+ if (IS_ERR(h_file))
19574+ goto out_fd;
19575+
acd2b654 19576+ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */
4a4d8108
AM
19577+ fd_install(fd, h_file);
19578+ err = fd;
19579+ goto out; /* success */
19580+
4f0767ce 19581+out_fd:
4a4d8108 19582+ put_unused_fd(fd);
4f0767ce 19583+out:
1e00d052 19584+ AuTraceErr(err);
4a4d8108
AM
19585+ return err;
19586+}
19587+
19588+/* ---------------------------------------------------------------------- */
19589+
19590+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
19591+{
19592+ long err;
c1595e42 19593+ struct dentry *dentry;
4a4d8108
AM
19594+
19595+ switch (cmd) {
4a4d8108
AM
19596+ case AUFS_CTL_RDU:
19597+ case AUFS_CTL_RDU_INO:
19598+ err = au_rdu_ioctl(file, cmd, arg);
19599+ break;
19600+
19601+ case AUFS_CTL_WBR_FD:
1e00d052 19602+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19603+ break;
19604+
027c5e7a
AM
19605+ case AUFS_CTL_IBUSY:
19606+ err = au_ibusy_ioctl(file, arg);
19607+ break;
19608+
076b876e
AM
19609+ case AUFS_CTL_BRINFO:
19610+ err = au_brinfo_ioctl(file, arg);
19611+ break;
19612+
19613+ case AUFS_CTL_FHSM_FD:
2000de60 19614+ dentry = file->f_path.dentry;
c1595e42
JR
19615+ if (IS_ROOT(dentry))
19616+ err = au_fhsm_fd(dentry->d_sb, arg);
19617+ else
19618+ err = -ENOTTY;
076b876e
AM
19619+ break;
19620+
4a4d8108
AM
19621+ default:
19622+ /* do not call the lower */
19623+ AuDbg("0x%x\n", cmd);
19624+ err = -ENOTTY;
19625+ }
19626+
19627+ AuTraceErr(err);
19628+ return err;
19629+}
19630+
19631+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
19632+{
19633+ long err;
19634+
19635+ switch (cmd) {
c2b27bf2 19636+ case AUFS_CTL_MVDOWN:
2000de60 19637+ err = au_mvdown(file->f_path.dentry, (void __user *)arg);
c2b27bf2
AM
19638+ break;
19639+
4a4d8108 19640+ case AUFS_CTL_WBR_FD:
1e00d052 19641+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19642+ break;
19643+
19644+ default:
19645+ /* do not call the lower */
19646+ AuDbg("0x%x\n", cmd);
19647+ err = -ENOTTY;
19648+ }
19649+
19650+ AuTraceErr(err);
19651+ return err;
19652+}
b752ccd1
AM
19653+
19654+#ifdef CONFIG_COMPAT
19655+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
19656+ unsigned long arg)
19657+{
19658+ long err;
19659+
19660+ switch (cmd) {
19661+ case AUFS_CTL_RDU:
19662+ case AUFS_CTL_RDU_INO:
19663+ err = au_rdu_compat_ioctl(file, cmd, arg);
19664+ break;
19665+
027c5e7a
AM
19666+ case AUFS_CTL_IBUSY:
19667+ err = au_ibusy_compat_ioctl(file, arg);
19668+ break;
19669+
076b876e
AM
19670+ case AUFS_CTL_BRINFO:
19671+ err = au_brinfo_compat_ioctl(file, arg);
19672+ break;
19673+
b752ccd1
AM
19674+ default:
19675+ err = aufs_ioctl_dir(file, cmd, arg);
19676+ }
19677+
19678+ AuTraceErr(err);
19679+ return err;
19680+}
19681+
b752ccd1
AM
19682+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
19683+ unsigned long arg)
19684+{
19685+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
19686+}
19687+#endif
7f207e10 19688diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
fbc438ed
JR
19689--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 08:00:00.000000000 +0800
19690+++ linux/fs/aufs/i_op_add.c 2019-07-11 21:21:54.382384486 +0800
eca801bf 19691@@ -0,0 +1,936 @@
cd7a4cd9 19692+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19693+/*
ba1aed25 19694+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
19695+ *
19696+ * This program, aufs is free software; you can redistribute it and/or modify
19697+ * it under the terms of the GNU General Public License as published by
19698+ * the Free Software Foundation; either version 2 of the License, or
19699+ * (at your option) any later version.
19700+ *
19701+ * This program is distributed in the hope that it will be useful,
19702+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19703+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19704+ * GNU General Public License for more details.
19705+ *
19706+ * You should have received a copy of the GNU General Public License
523b37e3 19707+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19708+ */
19709+
19710+/*
19711+ * inode operations (add entry)
19712+ */
19713+
eca801bf 19714+#include <linux/iversion.h>
4a4d8108
AM
19715+#include "aufs.h"
19716+
19717+/*
19718+ * final procedure of adding a new entry, except link(2).
19719+ * remove whiteout, instantiate, copyup the parent dir's times and size
19720+ * and update version.
19721+ * if it failed, re-create the removed whiteout.
19722+ */
19723+static int epilog(struct inode *dir, aufs_bindex_t bindex,
19724+ struct dentry *wh_dentry, struct dentry *dentry)
19725+{
19726+ int err, rerr;
19727+ aufs_bindex_t bwh;
19728+ struct path h_path;
076b876e 19729+ struct super_block *sb;
4a4d8108
AM
19730+ struct inode *inode, *h_dir;
19731+ struct dentry *wh;
19732+
19733+ bwh = -1;
076b876e 19734+ sb = dir->i_sb;
4a4d8108 19735+ if (wh_dentry) {
5527c038 19736+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
4a4d8108
AM
19737+ IMustLock(h_dir);
19738+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
19739+ bwh = au_dbwh(dentry);
19740+ h_path.dentry = wh_dentry;
076b876e 19741+ h_path.mnt = au_sbr_mnt(sb, bindex);
4a4d8108
AM
19742+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
19743+ dentry);
19744+ if (unlikely(err))
19745+ goto out;
19746+ }
19747+
19748+ inode = au_new_inode(dentry, /*must_new*/1);
19749+ if (!IS_ERR(inode)) {
19750+ d_instantiate(dentry, inode);
5527c038 19751+ dir = d_inode(dentry->d_parent); /* dir inode is locked */
4a4d8108 19752+ IMustLock(dir);
b912730e 19753+ au_dir_ts(dir, bindex);
be118d29 19754+ inode_inc_iversion(dir);
076b876e 19755+ au_fhsm_wrote(sb, bindex, /*force*/0);
4a4d8108
AM
19756+ return 0; /* success */
19757+ }
19758+
19759+ err = PTR_ERR(inode);
19760+ if (!wh_dentry)
19761+ goto out;
19762+
19763+ /* revert */
19764+ /* dir inode is locked */
19765+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
19766+ rerr = PTR_ERR(wh);
19767+ if (IS_ERR(wh)) {
523b37e3
AM
19768+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n",
19769+ dentry, err, rerr);
4a4d8108
AM
19770+ err = -EIO;
19771+ } else
19772+ dput(wh);
19773+
4f0767ce 19774+out:
4a4d8108
AM
19775+ return err;
19776+}
19777+
027c5e7a
AM
19778+static int au_d_may_add(struct dentry *dentry)
19779+{
19780+ int err;
19781+
19782+ err = 0;
19783+ if (unlikely(d_unhashed(dentry)))
19784+ err = -ENOENT;
5527c038 19785+ if (unlikely(d_really_is_positive(dentry)))
027c5e7a
AM
19786+ err = -EEXIST;
19787+ return err;
19788+}
19789+
4a4d8108
AM
19790+/*
19791+ * simple tests for the adding inode operations.
19792+ * following the checks in vfs, plus the parent-child relationship.
19793+ */
19794+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
19795+ struct dentry *h_parent, int isdir)
19796+{
19797+ int err;
19798+ umode_t h_mode;
19799+ struct dentry *h_dentry;
19800+ struct inode *h_inode;
19801+
19802+ err = -ENAMETOOLONG;
19803+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19804+ goto out;
19805+
19806+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 19807+ if (d_really_is_negative(dentry)) {
4a4d8108 19808+ err = -EEXIST;
5527c038 19809+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
19810+ goto out;
19811+ } else {
19812+ /* rename(2) case */
19813+ err = -EIO;
5527c038
JR
19814+ if (unlikely(d_is_negative(h_dentry)))
19815+ goto out;
19816+ h_inode = d_inode(h_dentry);
19817+ if (unlikely(!h_inode->i_nlink))
4a4d8108
AM
19818+ goto out;
19819+
19820+ h_mode = h_inode->i_mode;
19821+ if (!isdir) {
19822+ err = -EISDIR;
19823+ if (unlikely(S_ISDIR(h_mode)))
19824+ goto out;
19825+ } else if (unlikely(!S_ISDIR(h_mode))) {
19826+ err = -ENOTDIR;
19827+ goto out;
19828+ }
19829+ }
19830+
19831+ err = 0;
19832+ /* expected parent dir is locked */
19833+ if (unlikely(h_parent != h_dentry->d_parent))
19834+ err = -EIO;
19835+
4f0767ce 19836+out:
4a4d8108
AM
19837+ AuTraceErr(err);
19838+ return err;
19839+}
19840+
19841+/*
19842+ * initial procedure of adding a new entry.
19843+ * prepare writable branch and the parent dir, lock it,
19844+ * and lookup whiteout for the new entry.
19845+ */
19846+static struct dentry*
19847+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
19848+ struct dentry *src_dentry, struct au_pin *pin,
19849+ struct au_wr_dir_args *wr_dir_args)
19850+{
19851+ struct dentry *wh_dentry, *h_parent;
19852+ struct super_block *sb;
19853+ struct au_branch *br;
19854+ int err;
19855+ unsigned int udba;
19856+ aufs_bindex_t bcpup;
19857+
523b37e3 19858+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19859+
19860+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
19861+ bcpup = err;
19862+ wh_dentry = ERR_PTR(err);
19863+ if (unlikely(err < 0))
19864+ goto out;
19865+
19866+ sb = dentry->d_sb;
19867+ udba = au_opt_udba(sb);
19868+ err = au_pin(pin, dentry, bcpup, udba,
19869+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
19870+ wh_dentry = ERR_PTR(err);
19871+ if (unlikely(err))
19872+ goto out;
19873+
19874+ h_parent = au_pinned_h_parent(pin);
19875+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 19876+ && au_dbtop(dentry) == bcpup)
4a4d8108
AM
19877+ err = au_may_add(dentry, bcpup, h_parent,
19878+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
19879+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19880+ err = -ENAMETOOLONG;
19881+ wh_dentry = ERR_PTR(err);
19882+ if (unlikely(err))
19883+ goto out_unpin;
19884+
19885+ br = au_sbr(sb, bcpup);
19886+ if (dt) {
19887+ struct path tmp = {
19888+ .dentry = h_parent,
86dc4139 19889+ .mnt = au_br_mnt(br)
4a4d8108
AM
19890+ };
19891+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
19892+ }
19893+
19894+ wh_dentry = NULL;
19895+ if (bcpup != au_dbwh(dentry))
19896+ goto out; /* success */
19897+
2000de60
JR
19898+ /*
19899+ * ENAMETOOLONG here means that if we allowed create such name, then it
19900+ * would not be able to removed in the future. So we don't allow such
19901+ * name here and we don't handle ENAMETOOLONG differently here.
19902+ */
4a4d8108
AM
19903+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
19904+
4f0767ce 19905+out_unpin:
4a4d8108
AM
19906+ if (IS_ERR(wh_dentry))
19907+ au_unpin(pin);
4f0767ce 19908+out:
4a4d8108
AM
19909+ return wh_dentry;
19910+}
19911+
19912+/* ---------------------------------------------------------------------- */
19913+
19914+enum { Mknod, Symlink, Creat };
19915+struct simple_arg {
19916+ int type;
19917+ union {
19918+ struct {
b912730e
AM
19919+ umode_t mode;
19920+ bool want_excl;
19921+ bool try_aopen;
19922+ struct vfsub_aopen_args *aopen;
4a4d8108
AM
19923+ } c;
19924+ struct {
19925+ const char *symname;
19926+ } s;
19927+ struct {
7eafdf33 19928+ umode_t mode;
4a4d8108
AM
19929+ dev_t dev;
19930+ } m;
19931+ } u;
19932+};
19933+
19934+static int add_simple(struct inode *dir, struct dentry *dentry,
19935+ struct simple_arg *arg)
19936+{
076b876e 19937+ int err, rerr;
5afbbe0d 19938+ aufs_bindex_t btop;
4a4d8108 19939+ unsigned char created;
b912730e
AM
19940+ const unsigned char try_aopen
19941+ = (arg->type == Creat && arg->u.c.try_aopen);
acd2b654 19942+ struct vfsub_aopen_args *aopen = arg->u.c.aopen;
4a4d8108
AM
19943+ struct dentry *wh_dentry, *parent;
19944+ struct inode *h_dir;
b912730e
AM
19945+ struct super_block *sb;
19946+ struct au_branch *br;
acd2b654 19947+ /* to reduce stack size */
c2b27bf2
AM
19948+ struct {
19949+ struct au_dtime dt;
19950+ struct au_pin pin;
19951+ struct path h_path;
19952+ struct au_wr_dir_args wr_dir_args;
19953+ } *a;
4a4d8108 19954+
523b37e3 19955+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19956+ IMustLock(dir);
19957+
c2b27bf2
AM
19958+ err = -ENOMEM;
19959+ a = kmalloc(sizeof(*a), GFP_NOFS);
19960+ if (unlikely(!a))
19961+ goto out;
19962+ a->wr_dir_args.force_btgt = -1;
19963+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY;
19964+
4a4d8108 19965+ parent = dentry->d_parent; /* dir inode is locked */
b912730e
AM
19966+ if (!try_aopen) {
19967+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
19968+ if (unlikely(err))
19969+ goto out_free;
19970+ }
027c5e7a
AM
19971+ err = au_d_may_add(dentry);
19972+ if (unlikely(err))
19973+ goto out_unlock;
b912730e
AM
19974+ if (!try_aopen)
19975+ di_write_lock_parent(parent);
c2b27bf2
AM
19976+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
19977+ &a->pin, &a->wr_dir_args);
4a4d8108
AM
19978+ err = PTR_ERR(wh_dentry);
19979+ if (IS_ERR(wh_dentry))
027c5e7a 19980+ goto out_parent;
4a4d8108 19981+
5afbbe0d 19982+ btop = au_dbtop(dentry);
b912730e 19983+ sb = dentry->d_sb;
5afbbe0d
AM
19984+ br = au_sbr(sb, btop);
19985+ a->h_path.dentry = au_h_dptr(dentry, btop);
b912730e 19986+ a->h_path.mnt = au_br_mnt(br);
c2b27bf2 19987+ h_dir = au_pinned_h_dir(&a->pin);
4a4d8108
AM
19988+ switch (arg->type) {
19989+ case Creat:
acd2b654 19990+ if (!try_aopen || !h_dir->i_op->atomic_open) {
b912730e
AM
19991+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode,
19992+ arg->u.c.want_excl);
acd2b654
AM
19993+ created = !err;
19994+ if (!err && try_aopen)
19995+ aopen->file->f_mode |= FMODE_CREATED;
19996+ } else {
19997+ aopen->br = br;
19998+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen);
19999+ AuDbg("err %d\n", err);
20000+ AuDbgFile(aopen->file);
20001+ created = err >= 0
20002+ && !!(aopen->file->f_mode & FMODE_CREATED);
20003+ }
4a4d8108
AM
20004+ break;
20005+ case Symlink:
c2b27bf2 20006+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname);
acd2b654 20007+ created = !err;
4a4d8108
AM
20008+ break;
20009+ case Mknod:
c2b27bf2
AM
20010+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode,
20011+ arg->u.m.dev);
acd2b654 20012+ created = !err;
4a4d8108
AM
20013+ break;
20014+ default:
20015+ BUG();
20016+ }
acd2b654
AM
20017+ if (unlikely(err < 0))
20018+ goto out_unpin;
20019+
20020+ err = epilog(dir, btop, wh_dentry, dentry);
4a4d8108 20021+ if (!err)
acd2b654 20022+ goto out_unpin; /* success */
4a4d8108
AM
20023+
20024+ /* revert */
acd2b654 20025+ if (created /* && d_is_positive(a->h_path.dentry) */) {
523b37e3
AM
20026+ /* no delegation since it is just created */
20027+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL,
20028+ /*force*/0);
4a4d8108 20029+ if (rerr) {
523b37e3
AM
20030+ AuIOErr("%pd revert failure(%d, %d)\n",
20031+ dentry, err, rerr);
4a4d8108
AM
20032+ err = -EIO;
20033+ }
c2b27bf2 20034+ au_dtime_revert(&a->dt);
4a4d8108 20035+ }
acd2b654
AM
20036+ if (try_aopen && h_dir->i_op->atomic_open
20037+ && (aopen->file->f_mode & FMODE_OPENED))
20038+ /* aopen->file is still opened */
20039+ au_lcnt_dec(&aopen->br->br_nfiles);
4a4d8108 20040+
acd2b654 20041+out_unpin:
c2b27bf2 20042+ au_unpin(&a->pin);
4a4d8108 20043+ dput(wh_dentry);
027c5e7a 20044+out_parent:
b912730e
AM
20045+ if (!try_aopen)
20046+ di_write_unlock(parent);
027c5e7a 20047+out_unlock:
4a4d8108 20048+ if (unlikely(err)) {
5afbbe0d 20049+ au_update_dbtop(dentry);
4a4d8108
AM
20050+ d_drop(dentry);
20051+ }
b912730e
AM
20052+ if (!try_aopen)
20053+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 20054+out_free:
9f237c51 20055+ au_kfree_rcu(a);
027c5e7a 20056+out:
4a4d8108
AM
20057+ return err;
20058+}
20059+
7eafdf33
AM
20060+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
20061+ dev_t dev)
4a4d8108
AM
20062+{
20063+ struct simple_arg arg = {
20064+ .type = Mknod,
20065+ .u.m = {
20066+ .mode = mode,
20067+ .dev = dev
20068+ }
20069+ };
20070+ return add_simple(dir, dentry, &arg);
20071+}
20072+
20073+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
20074+{
20075+ struct simple_arg arg = {
20076+ .type = Symlink,
20077+ .u.s.symname = symname
20078+ };
20079+ return add_simple(dir, dentry, &arg);
20080+}
20081+
7eafdf33 20082+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 20083+ bool want_excl)
4a4d8108
AM
20084+{
20085+ struct simple_arg arg = {
20086+ .type = Creat,
20087+ .u.c = {
b4510431
AM
20088+ .mode = mode,
20089+ .want_excl = want_excl
4a4d8108
AM
20090+ }
20091+ };
20092+ return add_simple(dir, dentry, &arg);
20093+}
20094+
b912730e
AM
20095+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
20096+ struct vfsub_aopen_args *aopen_args)
20097+{
20098+ struct simple_arg arg = {
20099+ .type = Creat,
20100+ .u.c = {
20101+ .mode = aopen_args->create_mode,
20102+ .want_excl = aopen_args->open_flag & O_EXCL,
20103+ .try_aopen = true,
20104+ .aopen = aopen_args
20105+ }
20106+ };
20107+ return add_simple(dir, dentry, &arg);
20108+}
20109+
38d290e6
JR
20110+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
20111+{
20112+ int err;
20113+ aufs_bindex_t bindex;
20114+ struct super_block *sb;
20115+ struct dentry *parent, *h_parent, *h_dentry;
20116+ struct inode *h_dir, *inode;
20117+ struct vfsmount *h_mnt;
20118+ struct au_wr_dir_args wr_dir_args = {
20119+ .force_btgt = -1,
20120+ .flags = AuWrDir_TMPFILE
20121+ };
20122+
20123+ /* copy-up may happen */
febd17d6 20124+ inode_lock(dir);
38d290e6
JR
20125+
20126+ sb = dir->i_sb;
20127+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20128+ if (unlikely(err))
20129+ goto out;
20130+
20131+ err = au_di_init(dentry);
20132+ if (unlikely(err))
20133+ goto out_si;
20134+
20135+ err = -EBUSY;
20136+ parent = d_find_any_alias(dir);
20137+ AuDebugOn(!parent);
20138+ di_write_lock_parent(parent);
5527c038 20139+ if (unlikely(d_inode(parent) != dir))
38d290e6
JR
20140+ goto out_parent;
20141+
20142+ err = au_digen_test(parent, au_sigen(sb));
20143+ if (unlikely(err))
20144+ goto out_parent;
20145+
5afbbe0d
AM
20146+ bindex = au_dbtop(parent);
20147+ au_set_dbtop(dentry, bindex);
20148+ au_set_dbbot(dentry, bindex);
38d290e6
JR
20149+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
20150+ bindex = err;
20151+ if (unlikely(err < 0))
20152+ goto out_parent;
20153+
20154+ err = -EOPNOTSUPP;
20155+ h_dir = au_h_iptr(dir, bindex);
20156+ if (unlikely(!h_dir->i_op->tmpfile))
20157+ goto out_parent;
20158+
20159+ h_mnt = au_sbr_mnt(sb, bindex);
20160+ err = vfsub_mnt_want_write(h_mnt);
20161+ if (unlikely(err))
20162+ goto out_parent;
20163+
20164+ h_parent = au_h_dptr(parent, bindex);
521ced18
JR
20165+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0);
20166+ if (IS_ERR(h_dentry)) {
20167+ err = PTR_ERR(h_dentry);
38d290e6 20168+ goto out_mnt;
521ced18 20169+ }
38d290e6 20170+
5afbbe0d
AM
20171+ au_set_dbtop(dentry, bindex);
20172+ au_set_dbbot(dentry, bindex);
38d290e6
JR
20173+ au_set_h_dptr(dentry, bindex, dget(h_dentry));
20174+ inode = au_new_inode(dentry, /*must_new*/1);
20175+ if (IS_ERR(inode)) {
20176+ err = PTR_ERR(inode);
20177+ au_set_h_dptr(dentry, bindex, NULL);
5afbbe0d
AM
20178+ au_set_dbtop(dentry, -1);
20179+ au_set_dbbot(dentry, -1);
38d290e6
JR
20180+ } else {
20181+ if (!inode->i_nlink)
20182+ set_nlink(inode, 1);
20183+ d_tmpfile(dentry, inode);
20184+ au_di(dentry)->di_tmpfile = 1;
20185+
20186+ /* update without i_mutex */
5afbbe0d 20187+ if (au_ibtop(dir) == au_dbtop(dentry))
38d290e6
JR
20188+ au_cpup_attr_timesizes(dir);
20189+ }
38d290e6 20190+ dput(h_dentry);
521ced18 20191+
38d290e6
JR
20192+out_mnt:
20193+ vfsub_mnt_drop_write(h_mnt);
20194+out_parent:
20195+ di_write_unlock(parent);
20196+ dput(parent);
20197+ di_write_unlock(dentry);
5afbbe0d 20198+ if (unlikely(err)) {
38d290e6
JR
20199+ au_di_fin(dentry);
20200+ dentry->d_fsdata = NULL;
20201+ }
20202+out_si:
20203+ si_read_unlock(sb);
20204+out:
febd17d6 20205+ inode_unlock(dir);
38d290e6
JR
20206+ return err;
20207+}
20208+
4a4d8108
AM
20209+/* ---------------------------------------------------------------------- */
20210+
20211+struct au_link_args {
20212+ aufs_bindex_t bdst, bsrc;
20213+ struct au_pin pin;
20214+ struct path h_path;
20215+ struct dentry *src_parent, *parent;
20216+};
20217+
20218+static int au_cpup_before_link(struct dentry *src_dentry,
20219+ struct au_link_args *a)
20220+{
20221+ int err;
20222+ struct dentry *h_src_dentry;
c2b27bf2
AM
20223+ struct au_cp_generic cpg = {
20224+ .dentry = src_dentry,
20225+ .bdst = a->bdst,
20226+ .bsrc = a->bsrc,
20227+ .len = -1,
20228+ .pin = &a->pin,
20229+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */
20230+ };
4a4d8108
AM
20231+
20232+ di_read_lock_parent(a->src_parent, AuLock_IR);
20233+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
20234+ if (unlikely(err))
20235+ goto out;
20236+
20237+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
4a4d8108
AM
20238+ err = au_pin(&a->pin, src_dentry, a->bdst,
20239+ au_opt_udba(src_dentry->d_sb),
20240+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20241+ if (unlikely(err))
20242+ goto out;
367653fa 20243+
c2b27bf2 20244+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
20245+ au_unpin(&a->pin);
20246+
4f0767ce 20247+out:
4a4d8108
AM
20248+ di_read_unlock(a->src_parent, AuLock_IR);
20249+ return err;
20250+}
20251+
86dc4139
AM
20252+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
20253+ struct au_link_args *a)
4a4d8108
AM
20254+{
20255+ int err;
20256+ unsigned char plink;
5afbbe0d 20257+ aufs_bindex_t bbot;
4a4d8108 20258+ struct dentry *h_src_dentry;
523b37e3 20259+ struct inode *h_inode, *inode, *delegated;
4a4d8108
AM
20260+ struct super_block *sb;
20261+ struct file *h_file;
20262+
20263+ plink = 0;
20264+ h_inode = NULL;
20265+ sb = src_dentry->d_sb;
5527c038 20266+ inode = d_inode(src_dentry);
5afbbe0d 20267+ if (au_ibtop(inode) <= a->bdst)
4a4d8108
AM
20268+ h_inode = au_h_iptr(inode, a->bdst);
20269+ if (!h_inode || !h_inode->i_nlink) {
20270+ /* copyup src_dentry as the name of dentry. */
5afbbe0d
AM
20271+ bbot = au_dbbot(dentry);
20272+ if (bbot < a->bsrc)
20273+ au_set_dbbot(dentry, a->bsrc);
86dc4139
AM
20274+ au_set_h_dptr(dentry, a->bsrc,
20275+ dget(au_h_dptr(src_dentry, a->bsrc)));
20276+ dget(a->h_path.dentry);
20277+ au_set_h_dptr(dentry, a->bdst, NULL);
c1595e42
JR
20278+ AuDbg("temporary d_inode...\n");
20279+ spin_lock(&dentry->d_lock);
5527c038 20280+ dentry->d_inode = d_inode(src_dentry); /* tmp */
c1595e42 20281+ spin_unlock(&dentry->d_lock);
392086de 20282+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0);
86dc4139 20283+ if (IS_ERR(h_file))
4a4d8108 20284+ err = PTR_ERR(h_file);
86dc4139 20285+ else {
c2b27bf2
AM
20286+ struct au_cp_generic cpg = {
20287+ .dentry = dentry,
20288+ .bdst = a->bdst,
20289+ .bsrc = -1,
20290+ .len = -1,
20291+ .pin = &a->pin,
20292+ .flags = AuCpup_KEEPLINO
20293+ };
20294+ err = au_sio_cpup_simple(&cpg);
86dc4139
AM
20295+ au_h_open_post(dentry, a->bsrc, h_file);
20296+ if (!err) {
20297+ dput(a->h_path.dentry);
20298+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20299+ } else
20300+ au_set_h_dptr(dentry, a->bdst,
20301+ a->h_path.dentry);
20302+ }
c1595e42 20303+ spin_lock(&dentry->d_lock);
86dc4139 20304+ dentry->d_inode = NULL; /* restore */
c1595e42
JR
20305+ spin_unlock(&dentry->d_lock);
20306+ AuDbg("temporary d_inode...done\n");
86dc4139 20307+ au_set_h_dptr(dentry, a->bsrc, NULL);
5afbbe0d 20308+ au_set_dbbot(dentry, bbot);
4a4d8108
AM
20309+ } else {
20310+ /* the inode of src_dentry already exists on a.bdst branch */
20311+ h_src_dentry = d_find_alias(h_inode);
20312+ if (!h_src_dentry && au_plink_test(inode)) {
20313+ plink = 1;
20314+ h_src_dentry = au_plink_lkup(inode, a->bdst);
20315+ err = PTR_ERR(h_src_dentry);
20316+ if (IS_ERR(h_src_dentry))
20317+ goto out;
20318+
5527c038 20319+ if (unlikely(d_is_negative(h_src_dentry))) {
4a4d8108
AM
20320+ dput(h_src_dentry);
20321+ h_src_dentry = NULL;
20322+ }
20323+
20324+ }
20325+ if (h_src_dentry) {
523b37e3 20326+ delegated = NULL;
4a4d8108 20327+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20328+ &a->h_path, &delegated);
20329+ if (unlikely(err == -EWOULDBLOCK)) {
20330+ pr_warn("cannot retry for NFSv4 delegation"
20331+ " for an internal link\n");
20332+ iput(delegated);
20333+ }
4a4d8108
AM
20334+ dput(h_src_dentry);
20335+ } else {
20336+ AuIOErr("no dentry found for hi%lu on b%d\n",
20337+ h_inode->i_ino, a->bdst);
20338+ err = -EIO;
20339+ }
20340+ }
20341+
20342+ if (!err && !plink)
20343+ au_plink_append(inode, a->bdst, a->h_path.dentry);
20344+
20345+out:
2cbb1c4b 20346+ AuTraceErr(err);
4a4d8108
AM
20347+ return err;
20348+}
20349+
20350+int aufs_link(struct dentry *src_dentry, struct inode *dir,
20351+ struct dentry *dentry)
20352+{
20353+ int err, rerr;
20354+ struct au_dtime dt;
20355+ struct au_link_args *a;
20356+ struct dentry *wh_dentry, *h_src_dentry;
523b37e3 20357+ struct inode *inode, *delegated;
4a4d8108
AM
20358+ struct super_block *sb;
20359+ struct au_wr_dir_args wr_dir_args = {
20360+ /* .force_btgt = -1, */
20361+ .flags = AuWrDir_ADD_ENTRY
20362+ };
20363+
20364+ IMustLock(dir);
5527c038 20365+ inode = d_inode(src_dentry);
4a4d8108
AM
20366+ IMustLock(inode);
20367+
4a4d8108
AM
20368+ err = -ENOMEM;
20369+ a = kzalloc(sizeof(*a), GFP_NOFS);
20370+ if (unlikely(!a))
20371+ goto out;
20372+
20373+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
20374+ err = aufs_read_and_write_lock2(dentry, src_dentry,
20375+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
20376+ if (unlikely(err))
20377+ goto out_kfree;
38d290e6 20378+ err = au_d_linkable(src_dentry);
027c5e7a
AM
20379+ if (unlikely(err))
20380+ goto out_unlock;
20381+ err = au_d_may_add(dentry);
20382+ if (unlikely(err))
20383+ goto out_unlock;
e49829fe 20384+
4a4d8108 20385+ a->src_parent = dget_parent(src_dentry);
5afbbe0d 20386+ wr_dir_args.force_btgt = au_ibtop(inode);
4a4d8108
AM
20387+
20388+ di_write_lock_parent(a->parent);
20389+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
20390+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
20391+ &wr_dir_args);
20392+ err = PTR_ERR(wh_dentry);
20393+ if (IS_ERR(wh_dentry))
027c5e7a 20394+ goto out_parent;
4a4d8108
AM
20395+
20396+ err = 0;
20397+ sb = dentry->d_sb;
5afbbe0d 20398+ a->bdst = au_dbtop(dentry);
4a4d8108
AM
20399+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20400+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
5afbbe0d 20401+ a->bsrc = au_ibtop(inode);
2cbb1c4b 20402+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
38d290e6
JR
20403+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile)
20404+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc));
2cbb1c4b 20405+ if (!h_src_dentry) {
5afbbe0d 20406+ a->bsrc = au_dbtop(src_dentry);
2cbb1c4b
JR
20407+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
20408+ AuDebugOn(!h_src_dentry);
38d290e6
JR
20409+ } else if (IS_ERR(h_src_dentry)) {
20410+ err = PTR_ERR(h_src_dentry);
2cbb1c4b 20411+ goto out_parent;
38d290e6 20412+ }
2cbb1c4b 20413+
f2c43d5f
AM
20414+ /*
20415+ * aufs doesn't touch the credential so
acd2b654 20416+ * security_dentry_create_files_as() is unnecessary.
f2c43d5f 20417+ */
4a4d8108
AM
20418+ if (au_opt_test(au_mntflags(sb), PLINK)) {
20419+ if (a->bdst < a->bsrc
20420+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
86dc4139 20421+ err = au_cpup_or_link(src_dentry, dentry, a);
523b37e3
AM
20422+ else {
20423+ delegated = NULL;
4a4d8108 20424+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20425+ &a->h_path, &delegated);
20426+ if (unlikely(err == -EWOULDBLOCK)) {
20427+ pr_warn("cannot retry for NFSv4 delegation"
20428+ " for an internal link\n");
20429+ iput(delegated);
20430+ }
20431+ }
2cbb1c4b 20432+ dput(h_src_dentry);
4a4d8108
AM
20433+ } else {
20434+ /*
20435+ * copyup src_dentry to the branch we process,
20436+ * and then link(2) to it.
20437+ */
2cbb1c4b 20438+ dput(h_src_dentry);
4a4d8108
AM
20439+ if (a->bdst < a->bsrc
20440+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
20441+ au_unpin(&a->pin);
20442+ di_write_unlock(a->parent);
20443+ err = au_cpup_before_link(src_dentry, a);
20444+ di_write_lock_parent(a->parent);
20445+ if (!err)
20446+ err = au_pin(&a->pin, dentry, a->bdst,
20447+ au_opt_udba(sb),
20448+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20449+ if (unlikely(err))
20450+ goto out_wh;
20451+ }
20452+ if (!err) {
20453+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
20454+ err = -ENOENT;
5527c038 20455+ if (h_src_dentry && d_is_positive(h_src_dentry)) {
523b37e3 20456+ delegated = NULL;
4a4d8108
AM
20457+ err = vfsub_link(h_src_dentry,
20458+ au_pinned_h_dir(&a->pin),
523b37e3
AM
20459+ &a->h_path, &delegated);
20460+ if (unlikely(err == -EWOULDBLOCK)) {
20461+ pr_warn("cannot retry"
20462+ " for NFSv4 delegation"
20463+ " for an internal link\n");
20464+ iput(delegated);
20465+ }
20466+ }
4a4d8108
AM
20467+ }
20468+ }
20469+ if (unlikely(err))
20470+ goto out_unpin;
20471+
20472+ if (wh_dentry) {
20473+ a->h_path.dentry = wh_dentry;
20474+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
20475+ dentry);
20476+ if (unlikely(err))
20477+ goto out_revert;
20478+ }
20479+
b912730e 20480+ au_dir_ts(dir, a->bdst);
be118d29 20481+ inode_inc_iversion(dir);
4a4d8108
AM
20482+ inc_nlink(inode);
20483+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
20484+ d_instantiate(dentry, au_igrab(inode));
20485+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
20486+ /* some filesystem calls d_drop() */
20487+ d_drop(dentry);
076b876e
AM
20488+ /* some filesystems consume an inode even hardlink */
20489+ au_fhsm_wrote(sb, a->bdst, /*force*/0);
4a4d8108
AM
20490+ goto out_unpin; /* success */
20491+
4f0767ce 20492+out_revert:
523b37e3
AM
20493+ /* no delegation since it is just created */
20494+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path,
20495+ /*delegated*/NULL, /*force*/0);
027c5e7a 20496+ if (unlikely(rerr)) {
523b37e3 20497+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr);
027c5e7a
AM
20498+ err = -EIO;
20499+ }
4a4d8108 20500+ au_dtime_revert(&dt);
4f0767ce 20501+out_unpin:
4a4d8108 20502+ au_unpin(&a->pin);
4f0767ce 20503+out_wh:
4a4d8108 20504+ dput(wh_dentry);
027c5e7a
AM
20505+out_parent:
20506+ di_write_unlock(a->parent);
20507+ dput(a->src_parent);
4f0767ce 20508+out_unlock:
4a4d8108 20509+ if (unlikely(err)) {
5afbbe0d 20510+ au_update_dbtop(dentry);
4a4d8108
AM
20511+ d_drop(dentry);
20512+ }
4a4d8108 20513+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 20514+out_kfree:
9f237c51 20515+ au_kfree_rcu(a);
4f0767ce 20516+out:
86dc4139 20517+ AuTraceErr(err);
4a4d8108
AM
20518+ return err;
20519+}
20520+
7eafdf33 20521+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
20522+{
20523+ int err, rerr;
20524+ aufs_bindex_t bindex;
20525+ unsigned char diropq;
20526+ struct path h_path;
20527+ struct dentry *wh_dentry, *parent, *opq_dentry;
febd17d6 20528+ struct inode *h_inode;
4a4d8108
AM
20529+ struct super_block *sb;
20530+ struct {
20531+ struct au_pin pin;
20532+ struct au_dtime dt;
20533+ } *a; /* reduce the stack usage */
20534+ struct au_wr_dir_args wr_dir_args = {
20535+ .force_btgt = -1,
20536+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
20537+ };
20538+
20539+ IMustLock(dir);
20540+
20541+ err = -ENOMEM;
20542+ a = kmalloc(sizeof(*a), GFP_NOFS);
20543+ if (unlikely(!a))
20544+ goto out;
20545+
027c5e7a
AM
20546+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
20547+ if (unlikely(err))
20548+ goto out_free;
20549+ err = au_d_may_add(dentry);
20550+ if (unlikely(err))
20551+ goto out_unlock;
20552+
4a4d8108
AM
20553+ parent = dentry->d_parent; /* dir inode is locked */
20554+ di_write_lock_parent(parent);
20555+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
20556+ &a->pin, &wr_dir_args);
20557+ err = PTR_ERR(wh_dentry);
20558+ if (IS_ERR(wh_dentry))
027c5e7a 20559+ goto out_parent;
4a4d8108
AM
20560+
20561+ sb = dentry->d_sb;
5afbbe0d 20562+ bindex = au_dbtop(dentry);
4a4d8108
AM
20563+ h_path.dentry = au_h_dptr(dentry, bindex);
20564+ h_path.mnt = au_sbr_mnt(sb, bindex);
20565+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
20566+ if (unlikely(err))
027c5e7a 20567+ goto out_unpin;
4a4d8108
AM
20568+
20569+ /* make the dir opaque */
20570+ diropq = 0;
febd17d6 20571+ h_inode = d_inode(h_path.dentry);
4a4d8108
AM
20572+ if (wh_dentry
20573+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
febd17d6 20574+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20575+ opq_dentry = au_diropq_create(dentry, bindex);
febd17d6 20576+ inode_unlock(h_inode);
4a4d8108
AM
20577+ err = PTR_ERR(opq_dentry);
20578+ if (IS_ERR(opq_dentry))
20579+ goto out_dir;
20580+ dput(opq_dentry);
20581+ diropq = 1;
20582+ }
20583+
20584+ err = epilog(dir, bindex, wh_dentry, dentry);
20585+ if (!err) {
20586+ inc_nlink(dir);
027c5e7a 20587+ goto out_unpin; /* success */
4a4d8108
AM
20588+ }
20589+
20590+ /* revert */
20591+ if (diropq) {
20592+ AuLabel(revert opq);
febd17d6 20593+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20594+ rerr = au_diropq_remove(dentry, bindex);
febd17d6 20595+ inode_unlock(h_inode);
4a4d8108 20596+ if (rerr) {
523b37e3
AM
20597+ AuIOErr("%pd reverting diropq failed(%d, %d)\n",
20598+ dentry, err, rerr);
4a4d8108
AM
20599+ err = -EIO;
20600+ }
20601+ }
20602+
4f0767ce 20603+out_dir:
4a4d8108
AM
20604+ AuLabel(revert dir);
20605+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
20606+ if (rerr) {
523b37e3
AM
20607+ AuIOErr("%pd reverting dir failed(%d, %d)\n",
20608+ dentry, err, rerr);
4a4d8108
AM
20609+ err = -EIO;
20610+ }
4a4d8108 20611+ au_dtime_revert(&a->dt);
027c5e7a 20612+out_unpin:
4a4d8108
AM
20613+ au_unpin(&a->pin);
20614+ dput(wh_dentry);
027c5e7a
AM
20615+out_parent:
20616+ di_write_unlock(parent);
20617+out_unlock:
4a4d8108 20618+ if (unlikely(err)) {
5afbbe0d 20619+ au_update_dbtop(dentry);
4a4d8108
AM
20620+ d_drop(dentry);
20621+ }
4a4d8108 20622+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 20623+out_free:
9f237c51 20624+ au_kfree_rcu(a);
4f0767ce 20625+out:
4a4d8108
AM
20626+ return err;
20627+}
7f207e10 20628diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
fbc438ed
JR
20629--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 08:00:00.000000000 +0800
20630+++ linux/fs/aufs/i_op.c 2019-07-11 21:21:54.379051070 +0800
eca801bf 20631@@ -0,0 +1,1507 @@
cd7a4cd9 20632+// SPDX-License-Identifier: GPL-2.0
4a4d8108 20633+/*
ba1aed25 20634+ * Copyright (C) 2005-2019 Junjiro R. Okajima
4a4d8108
AM
20635+ *
20636+ * This program, aufs is free software; you can redistribute it and/or modify
20637+ * it under the terms of the GNU General Public License as published by
20638+ * the Free Software Foundation; either version 2 of the License, or
20639+ * (at your option) any later version.
20640+ *
20641+ * This program is distributed in the hope that it will be useful,
20642+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20643+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20644+ * GNU General Public License for more details.
20645+ *
20646+ * You should have received a copy of the GNU General Public License
523b37e3 20647+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 20648+ */
1facf9fc 20649+
1308ab2a 20650+/*
4a4d8108 20651+ * inode operations (except add/del/rename)
1308ab2a 20652+ */
4a4d8108
AM
20653+
20654+#include <linux/device_cgroup.h>
20655+#include <linux/fs_stack.h>
eca801bf 20656+#include <linux/iversion.h>
4a4d8108
AM
20657+#include <linux/namei.h>
20658+#include <linux/security.h>
4a4d8108
AM
20659+#include "aufs.h"
20660+
1e00d052 20661+static int h_permission(struct inode *h_inode, int mask,
79b8bda9 20662+ struct path *h_path, int brperm)
1facf9fc 20663+{
1308ab2a 20664+ int err;
4a4d8108 20665+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 20666+
e2f27e51
AM
20667+ err = -EPERM;
20668+ if (write_mask && IS_IMMUTABLE(h_inode))
20669+ goto out;
20670+
4a4d8108 20671+ err = -EACCES;
e2f27e51
AM
20672+ if (((mask & MAY_EXEC)
20673+ && S_ISREG(h_inode->i_mode)
20674+ && (path_noexec(h_path)
cd7a4cd9 20675+ || !(h_inode->i_mode & 0111))))
4a4d8108
AM
20676+ goto out;
20677+
20678+ /*
20679+ * - skip the lower fs test in the case of write to ro branch.
20680+ * - nfs dir permission write check is optimized, but a policy for
20681+ * link/rename requires a real check.
2121bcd9 20682+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e 20683+ * in this case, generic_permission() returns -EOPNOTSUPP.
4a4d8108
AM
20684+ */
20685+ if ((write_mask && !au_br_writable(brperm))
20686+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
20687+ && write_mask && !(mask & MAY_READ))
20688+ || !h_inode->i_op->permission) {
20689+ /* AuLabel(generic_permission); */
062440b3 20690+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */
1e00d052 20691+ err = generic_permission(h_inode, mask);
b912730e
AM
20692+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode))
20693+ err = h_inode->i_op->permission(h_inode, mask);
20694+ AuTraceErr(err);
1308ab2a 20695+ } else {
4a4d8108 20696+ /* AuLabel(h_inode->permission); */
1e00d052 20697+ err = h_inode->i_op->permission(h_inode, mask);
4a4d8108
AM
20698+ AuTraceErr(err);
20699+ }
1facf9fc 20700+
4a4d8108
AM
20701+ if (!err)
20702+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 20703+ if (!err)
4a4d8108 20704+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
20705+
20706+#if 0
20707+ if (!err) {
20708+ /* todo: do we need to call ima_path_check()? */
20709+ struct path h_path = {
20710+ .dentry =
20711+ .mnt = h_mnt
20712+ };
20713+ err = ima_path_check(&h_path,
20714+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
20715+ IMA_COUNT_LEAVE);
1308ab2a 20716+ }
4a4d8108 20717+#endif
dece6358 20718+
4f0767ce 20719+out:
1308ab2a 20720+ return err;
20721+}
dece6358 20722+
1e00d052 20723+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 20724+{
20725+ int err;
5afbbe0d 20726+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
20727+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
20728+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
20729+ struct inode *h_inode;
20730+ struct super_block *sb;
20731+ struct au_branch *br;
1facf9fc 20732+
027c5e7a 20733+ /* todo: support rcu-walk? */
1e00d052 20734+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
20735+ return -ECHILD;
20736+
4a4d8108
AM
20737+ sb = inode->i_sb;
20738+ si_read_lock(sb, AuLock_FLUSH);
20739+ ii_read_lock_child(inode);
027c5e7a
AM
20740+#if 0
20741+ err = au_iigen_test(inode, au_sigen(sb));
20742+ if (unlikely(err))
20743+ goto out;
20744+#endif
dece6358 20745+
076b876e
AM
20746+ if (!isdir
20747+ || write_mask
20748+ || au_opt_test(au_mntflags(sb), DIRPERM1)) {
4a4d8108 20749+ err = au_busy_or_stale();
5afbbe0d 20750+ h_inode = au_h_iptr(inode, au_ibtop(inode));
4a4d8108
AM
20751+ if (unlikely(!h_inode
20752+ || (h_inode->i_mode & S_IFMT)
20753+ != (inode->i_mode & S_IFMT)))
20754+ goto out;
1facf9fc 20755+
4a4d8108 20756+ err = 0;
5afbbe0d 20757+ bindex = au_ibtop(inode);
4a4d8108 20758+ br = au_sbr(sb, bindex);
79b8bda9 20759+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm);
4a4d8108
AM
20760+ if (write_mask
20761+ && !err
20762+ && !special_file(h_inode->i_mode)) {
20763+ /* test whether the upper writable branch exists */
20764+ err = -EROFS;
20765+ for (; bindex >= 0; bindex--)
20766+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
20767+ err = 0;
20768+ break;
20769+ }
20770+ }
20771+ goto out;
20772+ }
dece6358 20773+
4a4d8108 20774+ /* non-write to dir */
1308ab2a 20775+ err = 0;
5afbbe0d
AM
20776+ bbot = au_ibbot(inode);
20777+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
20778+ h_inode = au_h_iptr(inode, bindex);
20779+ if (h_inode) {
20780+ err = au_busy_or_stale();
20781+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
20782+ break;
20783+
20784+ br = au_sbr(sb, bindex);
79b8bda9 20785+ err = h_permission(h_inode, mask, &br->br_path,
4a4d8108
AM
20786+ br->br_perm);
20787+ }
20788+ }
1308ab2a 20789+
4f0767ce 20790+out:
4a4d8108
AM
20791+ ii_read_unlock(inode);
20792+ si_read_unlock(sb);
1308ab2a 20793+ return err;
20794+}
20795+
4a4d8108 20796+/* ---------------------------------------------------------------------- */
1facf9fc 20797+
4a4d8108 20798+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
b4510431 20799+ unsigned int flags)
4a4d8108
AM
20800+{
20801+ struct dentry *ret, *parent;
b752ccd1 20802+ struct inode *inode;
4a4d8108 20803+ struct super_block *sb;
1716fcea 20804+ int err, npositive;
dece6358 20805+
4a4d8108 20806+ IMustLock(dir);
1308ab2a 20807+
537831f9
AM
20808+ /* todo: support rcu-walk? */
20809+ ret = ERR_PTR(-ECHILD);
20810+ if (flags & LOOKUP_RCU)
20811+ goto out;
20812+
20813+ ret = ERR_PTR(-ENAMETOOLONG);
20814+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
20815+ goto out;
20816+
4a4d8108 20817+ sb = dir->i_sb;
7f207e10
AM
20818+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20819+ ret = ERR_PTR(err);
20820+ if (unlikely(err))
20821+ goto out;
20822+
4a4d8108
AM
20823+ err = au_di_init(dentry);
20824+ ret = ERR_PTR(err);
20825+ if (unlikely(err))
7f207e10 20826+ goto out_si;
1308ab2a 20827+
9dbd164d 20828+ inode = NULL;
027c5e7a 20829+ npositive = 0; /* suppress a warning */
4a4d8108
AM
20830+ parent = dentry->d_parent; /* dir inode is locked */
20831+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
20832+ err = au_alive_dir(parent);
20833+ if (!err)
20834+ err = au_digen_test(parent, au_sigen(sb));
20835+ if (!err) {
5afbbe0d
AM
20836+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */
20837+ npositive = au_lkup_dentry(dentry, au_dbtop(parent),
20838+ AuLkup_ALLOW_NEG);
027c5e7a
AM
20839+ err = npositive;
20840+ }
4a4d8108 20841+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
20842+ ret = ERR_PTR(err);
20843+ if (unlikely(err < 0))
20844+ goto out_unlock;
1308ab2a 20845+
4a4d8108 20846+ if (npositive) {
b752ccd1 20847+ inode = au_new_inode(dentry, /*must_new*/0);
c1595e42
JR
20848+ if (IS_ERR(inode)) {
20849+ ret = (void *)inode;
20850+ inode = NULL;
20851+ goto out_unlock;
20852+ }
9dbd164d 20853+ }
4a4d8108 20854+
c1595e42
JR
20855+ if (inode)
20856+ atomic_inc(&inode->i_count);
4a4d8108 20857+ ret = d_splice_alias(inode, dentry);
537831f9
AM
20858+#if 0
20859+ if (unlikely(d_need_lookup(dentry))) {
20860+ spin_lock(&dentry->d_lock);
20861+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
20862+ spin_unlock(&dentry->d_lock);
20863+ } else
20864+#endif
c1595e42 20865+ if (inode) {
2000de60 20866+ if (!IS_ERR(ret)) {
c1595e42 20867+ iput(inode);
2000de60
JR
20868+ if (ret && ret != dentry)
20869+ ii_write_unlock(inode);
20870+ } else {
c1595e42
JR
20871+ ii_write_unlock(inode);
20872+ iput(inode);
20873+ inode = NULL;
20874+ }
7f207e10 20875+ }
1facf9fc 20876+
4f0767ce 20877+out_unlock:
4a4d8108 20878+ di_write_unlock(dentry);
7f207e10 20879+out_si:
4a4d8108 20880+ si_read_unlock(sb);
7f207e10 20881+out:
4a4d8108
AM
20882+ return ret;
20883+}
1facf9fc 20884+
4a4d8108 20885+/* ---------------------------------------------------------------------- */
1facf9fc 20886+
acd2b654
AM
20887+/*
20888+ * very dirty and complicated aufs ->atomic_open().
20889+ * aufs_atomic_open()
20890+ * + au_aopen_or_create()
20891+ * + add_simple()
20892+ * + vfsub_atomic_open()
20893+ * + branch fs ->atomic_open()
20894+ * may call the actual 'open' for h_file
20895+ * + inc br_nfiles only if opened
20896+ * + au_aopen_no_open() or au_aopen_do_open()
20897+ *
20898+ * au_aopen_do_open()
20899+ * + finish_open()
20900+ * + au_do_aopen()
20901+ * + au_do_open() the body of all 'open'
20902+ * + au_do_open_nondir()
20903+ * set the passed h_file
20904+ *
20905+ * au_aopen_no_open()
20906+ * + finish_no_open()
20907+ */
20908+
b912730e 20909+struct aopen_node {
8b6a4947 20910+ struct hlist_bl_node hblist;
b912730e
AM
20911+ struct file *file, *h_file;
20912+};
20913+
20914+static int au_do_aopen(struct inode *inode, struct file *file)
20915+{
8b6a4947
AM
20916+ struct hlist_bl_head *aopen;
20917+ struct hlist_bl_node *pos;
b912730e
AM
20918+ struct aopen_node *node;
20919+ struct au_do_open_args args = {
8b6a4947
AM
20920+ .aopen = 1,
20921+ .open = au_do_open_nondir
b912730e
AM
20922+ };
20923+
20924+ aopen = &au_sbi(inode->i_sb)->si_aopen;
8b6a4947
AM
20925+ hlist_bl_lock(aopen);
20926+ hlist_bl_for_each_entry(node, pos, aopen, hblist)
b912730e
AM
20927+ if (node->file == file) {
20928+ args.h_file = node->h_file;
20929+ break;
20930+ }
8b6a4947 20931+ hlist_bl_unlock(aopen);
b912730e
AM
20932+ /* AuDebugOn(!args.h_file); */
20933+
20934+ return au_do_open(file, &args);
20935+}
20936+
acd2b654
AM
20937+static int au_aopen_do_open(struct file *file, struct dentry *dentry,
20938+ struct aopen_node *aopen_node)
20939+{
20940+ int err;
20941+ struct hlist_bl_head *aopen;
20942+
20943+ AuLabel(here);
20944+ aopen = &au_sbi(dentry->d_sb)->si_aopen;
20945+ au_hbl_add(&aopen_node->hblist, aopen);
20946+ err = finish_open(file, dentry, au_do_aopen);
20947+ au_hbl_del(&aopen_node->hblist, aopen);
20948+ /* AuDbgFile(file); */
20949+ AuDbg("%pd%s%s\n", dentry,
20950+ (file->f_mode & FMODE_CREATED) ? " created" : "",
20951+ (file->f_mode & FMODE_OPENED) ? " opened" : "");
20952+
20953+ AuTraceErr(err);
20954+ return err;
20955+}
20956+
20957+static int au_aopen_no_open(struct file *file, struct dentry *dentry)
20958+{
20959+ int err;
20960+
20961+ AuLabel(here);
20962+ dget(dentry);
20963+ err = finish_no_open(file, dentry);
20964+
20965+ AuTraceErr(err);
20966+ return err;
20967+}
20968+
b912730e
AM
20969+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
20970+ struct file *file, unsigned int open_flag,
acd2b654 20971+ umode_t create_mode)
b912730e 20972+{
acd2b654 20973+ int err, did_open;
5afbbe0d 20974+ unsigned int lkup_flags;
acd2b654
AM
20975+ aufs_bindex_t bindex;
20976+ struct super_block *sb;
f0c0a007 20977+ struct dentry *parent, *d;
b912730e
AM
20978+ struct vfsub_aopen_args args = {
20979+ .open_flag = open_flag,
acd2b654 20980+ .create_mode = create_mode
b912730e
AM
20981+ };
20982+ struct aopen_node aopen_node = {
20983+ .file = file
20984+ };
20985+
20986+ IMustLock(dir);
5afbbe0d 20987+ AuDbg("open_flag 0%o\n", open_flag);
b912730e
AM
20988+ AuDbgDentry(dentry);
20989+
20990+ err = 0;
20991+ if (!au_di(dentry)) {
5afbbe0d
AM
20992+ lkup_flags = LOOKUP_OPEN;
20993+ if (open_flag & O_CREAT)
20994+ lkup_flags |= LOOKUP_CREATE;
20995+ d = aufs_lookup(dir, dentry, lkup_flags);
b912730e
AM
20996+ if (IS_ERR(d)) {
20997+ err = PTR_ERR(d);
5afbbe0d 20998+ AuTraceErr(err);
b912730e
AM
20999+ goto out;
21000+ } else if (d) {
21001+ /*
21002+ * obsoleted dentry found.
21003+ * another error will be returned later.
21004+ */
21005+ d_drop(d);
b912730e 21006+ AuDbgDentry(d);
5afbbe0d 21007+ dput(d);
b912730e
AM
21008+ }
21009+ AuDbgDentry(dentry);
21010+ }
21011+
21012+ if (d_is_positive(dentry)
21013+ || d_unhashed(dentry)
21014+ || d_unlinked(dentry)
acd2b654
AM
21015+ || !(open_flag & O_CREAT)) {
21016+ err = au_aopen_no_open(file, dentry);
21017+ goto out; /* success */
21018+ }
b912730e
AM
21019+
21020+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
21021+ if (unlikely(err))
21022+ goto out;
21023+
acd2b654 21024+ sb = dentry->d_sb;
b912730e
AM
21025+ parent = dentry->d_parent; /* dir is locked */
21026+ di_write_lock_parent(parent);
5afbbe0d 21027+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
acd2b654
AM
21028+ if (unlikely(err < 0))
21029+ goto out_parent;
b912730e
AM
21030+
21031+ AuDbgDentry(dentry);
acd2b654
AM
21032+ if (d_is_positive(dentry)) {
21033+ err = au_aopen_no_open(file, dentry);
21034+ goto out_parent; /* success */
21035+ }
b912730e 21036+
acd2b654 21037+ args.file = alloc_empty_file(file->f_flags, current_cred());
b912730e
AM
21038+ err = PTR_ERR(args.file);
21039+ if (IS_ERR(args.file))
acd2b654 21040+ goto out_parent;
b912730e 21041+
acd2b654 21042+ bindex = au_dbtop(dentry);
b912730e
AM
21043+ err = au_aopen_or_create(dir, dentry, &args);
21044+ AuTraceErr(err);
21045+ AuDbgFile(args.file);
acd2b654
AM
21046+ file->f_mode = args.file->f_mode & ~FMODE_OPENED;
21047+ did_open = !!(args.file->f_mode & FMODE_OPENED);
21048+ if (!did_open) {
21049+ fput(args.file);
21050+ args.file = NULL;
b912730e 21051+ }
8b6a4947
AM
21052+ di_write_unlock(parent);
21053+ di_write_unlock(dentry);
acd2b654
AM
21054+ if (unlikely(err < 0)) {
21055+ if (args.file)
21056+ fput(args.file);
21057+ goto out_sb;
b912730e 21058+ }
b912730e 21059+
acd2b654
AM
21060+ if (!did_open)
21061+ err = au_aopen_no_open(file, dentry);
8b6a4947 21062+ else {
acd2b654
AM
21063+ aopen_node.h_file = args.file;
21064+ err = au_aopen_do_open(file, dentry, &aopen_node);
8b6a4947 21065+ }
acd2b654
AM
21066+ if (unlikely(err < 0)) {
21067+ if (args.file)
21068+ fput(args.file);
21069+ if (did_open)
21070+ au_lcnt_dec(&args.br->br_nfiles);
b912730e 21071+ }
acd2b654
AM
21072+ goto out_sb; /* success */
21073+
21074+out_parent:
21075+ di_write_unlock(parent);
21076+ di_write_unlock(dentry);
21077+out_sb:
21078+ si_read_unlock(sb);
b912730e 21079+out:
b912730e 21080+ AuTraceErr(err);
acd2b654 21081+ AuDbgFile(file);
b912730e
AM
21082+ return err;
21083+}
21084+
21085+
21086+/* ---------------------------------------------------------------------- */
21087+
4a4d8108
AM
21088+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
21089+ const unsigned char add_entry, aufs_bindex_t bcpup,
5afbbe0d 21090+ aufs_bindex_t btop)
4a4d8108
AM
21091+{
21092+ int err;
21093+ struct dentry *h_parent;
21094+ struct inode *h_dir;
1facf9fc 21095+
027c5e7a 21096+ if (add_entry)
5527c038 21097+ IMustLock(d_inode(parent));
027c5e7a 21098+ else
4a4d8108
AM
21099+ di_write_lock_parent(parent);
21100+
21101+ err = 0;
21102+ if (!au_h_dptr(parent, bcpup)) {
5afbbe0d 21103+ if (btop > bcpup)
c2b27bf2 21104+ err = au_cpup_dirs(dentry, bcpup);
5afbbe0d 21105+ else if (btop < bcpup)
4a4d8108
AM
21106+ err = au_cpdown_dirs(dentry, bcpup);
21107+ else
c2b27bf2 21108+ BUG();
4a4d8108 21109+ }
38d290e6 21110+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) {
4a4d8108 21111+ h_parent = au_h_dptr(parent, bcpup);
5527c038 21112+ h_dir = d_inode(h_parent);
be118d29 21113+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
7e9cd9fe 21114+ err = au_lkup_neg(dentry, bcpup, /*wh*/0);
4a4d8108 21115+ /* todo: no unlock here */
3c1bdaff 21116+ inode_unlock_shared(h_dir);
027c5e7a
AM
21117+
21118+ AuDbg("bcpup %d\n", bcpup);
21119+ if (!err) {
5527c038 21120+ if (d_really_is_negative(dentry))
5afbbe0d 21121+ au_set_h_dptr(dentry, btop, NULL);
4a4d8108
AM
21122+ au_update_dbrange(dentry, /*do_put_zero*/0);
21123+ }
1308ab2a 21124+ }
1facf9fc 21125+
4a4d8108
AM
21126+ if (!add_entry)
21127+ di_write_unlock(parent);
21128+ if (!err)
21129+ err = bcpup; /* success */
1308ab2a 21130+
027c5e7a 21131+ AuTraceErr(err);
4a4d8108
AM
21132+ return err;
21133+}
1facf9fc 21134+
4a4d8108
AM
21135+/*
21136+ * decide the branch and the parent dir where we will create a new entry.
21137+ * returns new bindex or an error.
21138+ * copyup the parent dir if needed.
21139+ */
21140+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
21141+ struct au_wr_dir_args *args)
21142+{
21143+ int err;
392086de 21144+ unsigned int flags;
5afbbe0d 21145+ aufs_bindex_t bcpup, btop, src_btop;
86dc4139
AM
21146+ const unsigned char add_entry
21147+ = au_ftest_wrdir(args->flags, ADD_ENTRY)
38d290e6 21148+ | au_ftest_wrdir(args->flags, TMPFILE);
4a4d8108
AM
21149+ struct super_block *sb;
21150+ struct dentry *parent;
21151+ struct au_sbinfo *sbinfo;
1facf9fc 21152+
4a4d8108
AM
21153+ sb = dentry->d_sb;
21154+ sbinfo = au_sbi(sb);
21155+ parent = dget_parent(dentry);
5afbbe0d
AM
21156+ btop = au_dbtop(dentry);
21157+ bcpup = btop;
4a4d8108
AM
21158+ if (args->force_btgt < 0) {
21159+ if (src_dentry) {
5afbbe0d
AM
21160+ src_btop = au_dbtop(src_dentry);
21161+ if (src_btop < btop)
21162+ bcpup = src_btop;
4a4d8108 21163+ } else if (add_entry) {
392086de
AM
21164+ flags = 0;
21165+ if (au_ftest_wrdir(args->flags, ISDIR))
21166+ au_fset_wbr(flags, DIR);
21167+ err = AuWbrCreate(sbinfo, dentry, flags);
4a4d8108
AM
21168+ bcpup = err;
21169+ }
1facf9fc 21170+
5527c038 21171+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) {
4a4d8108
AM
21172+ if (add_entry)
21173+ err = AuWbrCopyup(sbinfo, dentry);
21174+ else {
21175+ if (!IS_ROOT(dentry)) {
21176+ di_read_lock_parent(parent, !AuLock_IR);
21177+ err = AuWbrCopyup(sbinfo, dentry);
21178+ di_read_unlock(parent, !AuLock_IR);
21179+ } else
21180+ err = AuWbrCopyup(sbinfo, dentry);
21181+ }
21182+ bcpup = err;
21183+ if (unlikely(err < 0))
21184+ goto out;
21185+ }
21186+ } else {
21187+ bcpup = args->force_btgt;
5527c038 21188+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry)));
1308ab2a 21189+ }
027c5e7a 21190+
5afbbe0d 21191+ AuDbg("btop %d, bcpup %d\n", btop, bcpup);
4a4d8108 21192+ err = bcpup;
5afbbe0d 21193+ if (bcpup == btop)
4a4d8108 21194+ goto out; /* success */
4a4d8108
AM
21195+
21196+ /* copyup the new parent into the branch we process */
5afbbe0d 21197+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop);
027c5e7a 21198+ if (err >= 0) {
5527c038 21199+ if (d_really_is_negative(dentry)) {
5afbbe0d
AM
21200+ au_set_h_dptr(dentry, btop, NULL);
21201+ au_set_dbtop(dentry, bcpup);
21202+ au_set_dbbot(dentry, bcpup);
027c5e7a 21203+ }
38d290e6
JR
21204+ AuDebugOn(add_entry
21205+ && !au_ftest_wrdir(args->flags, TMPFILE)
21206+ && !au_h_dptr(dentry, bcpup));
027c5e7a 21207+ }
86dc4139
AM
21208+
21209+out:
21210+ dput(parent);
21211+ return err;
21212+}
21213+
21214+/* ---------------------------------------------------------------------- */
21215+
21216+void au_pin_hdir_unlock(struct au_pin *p)
21217+{
21218+ if (p->hdir)
5afbbe0d 21219+ au_hn_inode_unlock(p->hdir);
86dc4139
AM
21220+}
21221+
c1595e42 21222+int au_pin_hdir_lock(struct au_pin *p)
86dc4139
AM
21223+{
21224+ int err;
21225+
21226+ err = 0;
21227+ if (!p->hdir)
21228+ goto out;
21229+
21230+ /* even if an error happens later, keep this lock */
5afbbe0d 21231+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi);
86dc4139
AM
21232+
21233+ err = -EBUSY;
5527c038 21234+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent)))
86dc4139
AM
21235+ goto out;
21236+
21237+ err = 0;
21238+ if (p->h_dentry)
21239+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode,
21240+ p->h_parent, p->br);
21241+
21242+out:
21243+ return err;
21244+}
21245+
21246+int au_pin_hdir_relock(struct au_pin *p)
21247+{
21248+ int err, i;
21249+ struct inode *h_i;
21250+ struct dentry *h_d[] = {
21251+ p->h_dentry,
21252+ p->h_parent
21253+ };
21254+
21255+ err = au_pin_hdir_lock(p);
21256+ if (unlikely(err))
21257+ goto out;
21258+
21259+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) {
21260+ if (!h_d[i])
21261+ continue;
5527c038
JR
21262+ if (d_is_positive(h_d[i])) {
21263+ h_i = d_inode(h_d[i]);
86dc4139 21264+ err = !h_i->i_nlink;
5527c038 21265+ }
86dc4139
AM
21266+ }
21267+
21268+out:
21269+ return err;
21270+}
21271+
5afbbe0d 21272+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task)
86dc4139 21273+{
5afbbe0d
AM
21274+#if !defined(CONFIG_RWSEM_GENERIC_SPINLOCK) && defined(CONFIG_RWSEM_SPIN_ON_OWNER)
21275+ p->hdir->hi_inode->i_rwsem.owner = task;
86dc4139
AM
21276+#endif
21277+}
21278+
21279+void au_pin_hdir_acquire_nest(struct au_pin *p)
21280+{
21281+ if (p->hdir) {
5afbbe0d 21282+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map,
86dc4139
AM
21283+ p->lsc_hi, 0, NULL, _RET_IP_);
21284+ au_pin_hdir_set_owner(p, current);
21285+ }
dece6358 21286+}
1facf9fc 21287+
86dc4139
AM
21288+void au_pin_hdir_release(struct au_pin *p)
21289+{
21290+ if (p->hdir) {
21291+ au_pin_hdir_set_owner(p, p->task);
5afbbe0d 21292+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, 1, _RET_IP_);
86dc4139
AM
21293+ }
21294+}
1308ab2a 21295+
4a4d8108 21296+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 21297+{
4a4d8108
AM
21298+ if (pin && pin->parent)
21299+ return au_h_dptr(pin->parent, pin->bindex);
21300+ return NULL;
dece6358 21301+}
1facf9fc 21302+
4a4d8108 21303+void au_unpin(struct au_pin *p)
dece6358 21304+{
86dc4139
AM
21305+ if (p->hdir)
21306+ au_pin_hdir_unlock(p);
e49829fe 21307+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
b4510431 21308+ vfsub_mnt_drop_write(p->h_mnt);
4a4d8108
AM
21309+ if (!p->hdir)
21310+ return;
1facf9fc 21311+
4a4d8108
AM
21312+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21313+ di_read_unlock(p->parent, AuLock_IR);
21314+ iput(p->hdir->hi_inode);
21315+ dput(p->parent);
21316+ p->parent = NULL;
21317+ p->hdir = NULL;
21318+ p->h_mnt = NULL;
86dc4139 21319+ /* do not clear p->task */
4a4d8108 21320+}
1308ab2a 21321+
4a4d8108
AM
21322+int au_do_pin(struct au_pin *p)
21323+{
21324+ int err;
21325+ struct super_block *sb;
4a4d8108
AM
21326+ struct inode *h_dir;
21327+
21328+ err = 0;
21329+ sb = p->dentry->d_sb;
86dc4139 21330+ p->br = au_sbr(sb, p->bindex);
4a4d8108
AM
21331+ if (IS_ROOT(p->dentry)) {
21332+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21333+ p->h_mnt = au_br_mnt(p->br);
b4510431 21334+ err = vfsub_mnt_want_write(p->h_mnt);
4a4d8108
AM
21335+ if (unlikely(err)) {
21336+ au_fclr_pin(p->flags, MNT_WRITE);
21337+ goto out_err;
21338+ }
21339+ }
dece6358 21340+ goto out;
1facf9fc 21341+ }
21342+
86dc4139 21343+ p->h_dentry = NULL;
5afbbe0d 21344+ if (p->bindex <= au_dbbot(p->dentry))
86dc4139 21345+ p->h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 21346+
4a4d8108
AM
21347+ p->parent = dget_parent(p->dentry);
21348+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21349+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 21350+
4a4d8108 21351+ h_dir = NULL;
86dc4139 21352+ p->h_parent = au_h_dptr(p->parent, p->bindex);
5527c038 21353+ p->hdir = au_hi(d_inode(p->parent), p->bindex);
4a4d8108
AM
21354+ if (p->hdir)
21355+ h_dir = p->hdir->hi_inode;
dece6358 21356+
b752ccd1
AM
21357+ /*
21358+ * udba case, or
21359+ * if DI_LOCKED is not set, then p->parent may be different
21360+ * and h_parent can be NULL.
21361+ */
86dc4139 21362+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) {
e49829fe 21363+ err = -EBUSY;
4a4d8108
AM
21364+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21365+ di_read_unlock(p->parent, AuLock_IR);
21366+ dput(p->parent);
21367+ p->parent = NULL;
21368+ goto out_err;
21369+ }
1308ab2a 21370+
4a4d8108 21371+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21372+ p->h_mnt = au_br_mnt(p->br);
b4510431 21373+ err = vfsub_mnt_want_write(p->h_mnt);
dece6358 21374+ if (unlikely(err)) {
4a4d8108 21375+ au_fclr_pin(p->flags, MNT_WRITE);
86dc4139
AM
21376+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21377+ di_read_unlock(p->parent, AuLock_IR);
21378+ dput(p->parent);
21379+ p->parent = NULL;
21380+ goto out_err;
dece6358
AM
21381+ }
21382+ }
4a4d8108 21383+
86dc4139
AM
21384+ au_igrab(h_dir);
21385+ err = au_pin_hdir_lock(p);
21386+ if (!err)
21387+ goto out; /* success */
21388+
076b876e
AM
21389+ au_unpin(p);
21390+
4f0767ce 21391+out_err:
4a4d8108
AM
21392+ pr_err("err %d\n", err);
21393+ err = au_busy_or_stale();
4f0767ce 21394+out:
1facf9fc 21395+ return err;
21396+}
21397+
4a4d8108
AM
21398+void au_pin_init(struct au_pin *p, struct dentry *dentry,
21399+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
21400+ unsigned int udba, unsigned char flags)
21401+{
21402+ p->dentry = dentry;
21403+ p->udba = udba;
21404+ p->lsc_di = lsc_di;
21405+ p->lsc_hi = lsc_hi;
21406+ p->flags = flags;
21407+ p->bindex = bindex;
21408+
21409+ p->parent = NULL;
21410+ p->hdir = NULL;
21411+ p->h_mnt = NULL;
86dc4139
AM
21412+
21413+ p->h_dentry = NULL;
21414+ p->h_parent = NULL;
21415+ p->br = NULL;
21416+ p->task = current;
4a4d8108
AM
21417+}
21418+
21419+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
21420+ unsigned int udba, unsigned char flags)
21421+{
21422+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
21423+ udba, flags);
21424+ return au_do_pin(pin);
21425+}
21426+
dece6358
AM
21427+/* ---------------------------------------------------------------------- */
21428+
1308ab2a 21429+/*
4a4d8108
AM
21430+ * ->setattr() and ->getattr() are called in various cases.
21431+ * chmod, stat: dentry is revalidated.
21432+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
21433+ * unhashed.
21434+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 21435+ */
027c5e7a 21436+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
c1595e42 21437+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 21438+{
4a4d8108 21439+ int err;
4a4d8108 21440+ struct dentry *parent;
1facf9fc 21441+
1308ab2a 21442+ err = 0;
027c5e7a 21443+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
21444+ parent = dget_parent(dentry);
21445+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 21446+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
21447+ di_read_unlock(parent, AuLock_IR);
21448+ dput(parent);
dece6358 21449+ }
1facf9fc 21450+
4a4d8108 21451+ AuTraceErr(err);
1308ab2a 21452+ return err;
21453+}
dece6358 21454+
c1595e42
JR
21455+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
21456+ struct au_icpup_args *a)
1308ab2a 21457+{
21458+ int err;
4a4d8108 21459+ loff_t sz;
5afbbe0d 21460+ aufs_bindex_t btop, ibtop;
4a4d8108
AM
21461+ struct dentry *hi_wh, *parent;
21462+ struct inode *inode;
4a4d8108
AM
21463+ struct au_wr_dir_args wr_dir_args = {
21464+ .force_btgt = -1,
21465+ .flags = 0
21466+ };
21467+
2000de60 21468+ if (d_is_dir(dentry))
4a4d8108
AM
21469+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
21470+ /* plink or hi_wh() case */
5afbbe0d 21471+ btop = au_dbtop(dentry);
5527c038 21472+ inode = d_inode(dentry);
5afbbe0d
AM
21473+ ibtop = au_ibtop(inode);
21474+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode))
21475+ wr_dir_args.force_btgt = ibtop;
4a4d8108
AM
21476+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
21477+ if (unlikely(err < 0))
21478+ goto out;
21479+ a->btgt = err;
5afbbe0d 21480+ if (err != btop)
4a4d8108
AM
21481+ au_fset_icpup(a->flags, DID_CPUP);
21482+
21483+ err = 0;
21484+ a->pin_flags = AuPin_MNT_WRITE;
21485+ parent = NULL;
21486+ if (!IS_ROOT(dentry)) {
21487+ au_fset_pin(a->pin_flags, DI_LOCKED);
21488+ parent = dget_parent(dentry);
21489+ di_write_lock_parent(parent);
21490+ }
21491+
21492+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
21493+ if (unlikely(err))
21494+ goto out_parent;
21495+
4a4d8108 21496+ sz = -1;
5afbbe0d 21497+ a->h_path.dentry = au_h_dptr(dentry, btop);
5527c038 21498+ a->h_inode = d_inode(a->h_path.dentry);
c1595e42 21499+ if (ia && (ia->ia_valid & ATTR_SIZE)) {
be118d29 21500+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
c1595e42
JR
21501+ if (ia->ia_size < i_size_read(a->h_inode))
21502+ sz = ia->ia_size;
3c1bdaff 21503+ inode_unlock_shared(a->h_inode);
c1595e42 21504+ }
4a4d8108 21505+
4a4d8108 21506+ hi_wh = NULL;
027c5e7a 21507+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
21508+ hi_wh = au_hi_wh(inode, a->btgt);
21509+ if (!hi_wh) {
c2b27bf2
AM
21510+ struct au_cp_generic cpg = {
21511+ .dentry = dentry,
21512+ .bdst = a->btgt,
21513+ .bsrc = -1,
21514+ .len = sz,
21515+ .pin = &a->pin
21516+ };
21517+ err = au_sio_cpup_wh(&cpg, /*file*/NULL);
4a4d8108
AM
21518+ if (unlikely(err))
21519+ goto out_unlock;
21520+ hi_wh = au_hi_wh(inode, a->btgt);
21521+ /* todo: revalidate hi_wh? */
21522+ }
21523+ }
21524+
21525+ if (parent) {
21526+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
21527+ di_downgrade_lock(parent, AuLock_IR);
21528+ dput(parent);
21529+ parent = NULL;
21530+ }
21531+ if (!au_ftest_icpup(a->flags, DID_CPUP))
21532+ goto out; /* success */
21533+
21534+ if (!d_unhashed(dentry)) {
c2b27bf2
AM
21535+ struct au_cp_generic cpg = {
21536+ .dentry = dentry,
21537+ .bdst = a->btgt,
5afbbe0d 21538+ .bsrc = btop,
c2b27bf2
AM
21539+ .len = sz,
21540+ .pin = &a->pin,
21541+ .flags = AuCpup_DTIME | AuCpup_HOPEN
21542+ };
21543+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
21544+ if (!err)
21545+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21546+ } else if (!hi_wh)
21547+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21548+ else
21549+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 21550+
4f0767ce 21551+out_unlock:
5527c038 21552+ a->h_inode = d_inode(a->h_path.dentry);
86dc4139 21553+ if (!err)
dece6358 21554+ goto out; /* success */
4a4d8108 21555+ au_unpin(&a->pin);
4f0767ce 21556+out_parent:
4a4d8108
AM
21557+ if (parent) {
21558+ di_write_unlock(parent);
21559+ dput(parent);
21560+ }
4f0767ce 21561+out:
86dc4139 21562+ if (!err)
febd17d6 21563+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
1facf9fc 21564+ return err;
21565+}
21566+
4a4d8108 21567+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 21568+{
4a4d8108 21569+ int err;
523b37e3 21570+ struct inode *inode, *delegated;
4a4d8108
AM
21571+ struct super_block *sb;
21572+ struct file *file;
21573+ struct au_icpup_args *a;
1facf9fc 21574+
5527c038 21575+ inode = d_inode(dentry);
4a4d8108 21576+ IMustLock(inode);
dece6358 21577+
f2c43d5f
AM
21578+ err = setattr_prepare(dentry, ia);
21579+ if (unlikely(err))
21580+ goto out;
21581+
4a4d8108
AM
21582+ err = -ENOMEM;
21583+ a = kzalloc(sizeof(*a), GFP_NOFS);
21584+ if (unlikely(!a))
21585+ goto out;
1facf9fc 21586+
4a4d8108
AM
21587+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
21588+ ia->ia_valid &= ~ATTR_MODE;
dece6358 21589+
4a4d8108
AM
21590+ file = NULL;
21591+ sb = dentry->d_sb;
e49829fe
JR
21592+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21593+ if (unlikely(err))
21594+ goto out_kfree;
21595+
4a4d8108
AM
21596+ if (ia->ia_valid & ATTR_FILE) {
21597+ /* currently ftruncate(2) only */
7e9cd9fe 21598+ AuDebugOn(!d_is_reg(dentry));
4a4d8108 21599+ file = ia->ia_file;
521ced18
JR
21600+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
21601+ /*fi_lsc*/0);
4a4d8108
AM
21602+ if (unlikely(err))
21603+ goto out_si;
21604+ ia->ia_file = au_hf_top(file);
21605+ a->udba = AuOpt_UDBA_NONE;
21606+ } else {
21607+ /* fchmod() doesn't pass ia_file */
21608+ a->udba = au_opt_udba(sb);
027c5e7a
AM
21609+ di_write_lock_child(dentry);
21610+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
21611+ if (d_unhashed(dentry))
21612+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
21613+ if (a->udba != AuOpt_UDBA_NONE) {
21614+ AuDebugOn(IS_ROOT(dentry));
21615+ err = au_reval_for_attr(dentry, au_sigen(sb));
21616+ if (unlikely(err))
21617+ goto out_dentry;
21618+ }
dece6358 21619+ }
dece6358 21620+
4a4d8108
AM
21621+ err = au_pin_and_icpup(dentry, ia, a);
21622+ if (unlikely(err < 0))
21623+ goto out_dentry;
21624+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
21625+ ia->ia_file = NULL;
21626+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 21627+ }
dece6358 21628+
4a4d8108
AM
21629+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
21630+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
21631+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 21632+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
21633+ if (unlikely(err))
21634+ goto out_unlock;
21635+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
21636+ && (ia->ia_valid & ATTR_CTIME)) {
86dc4139 21637+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
4a4d8108
AM
21638+ if (unlikely(err))
21639+ goto out_unlock;
21640+ }
dece6358 21641+
4a4d8108
AM
21642+ if (ia->ia_valid & ATTR_SIZE) {
21643+ struct file *f;
1308ab2a 21644+
953406b4 21645+ if (ia->ia_size < i_size_read(inode))
4a4d8108 21646+ /* unmap only */
953406b4 21647+ truncate_setsize(inode, ia->ia_size);
1308ab2a 21648+
4a4d8108
AM
21649+ f = NULL;
21650+ if (ia->ia_valid & ATTR_FILE)
21651+ f = ia->ia_file;
febd17d6 21652+ inode_unlock(a->h_inode);
4a4d8108 21653+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
febd17d6 21654+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
523b37e3
AM
21655+ } else {
21656+ delegated = NULL;
21657+ while (1) {
21658+ err = vfsub_notify_change(&a->h_path, ia, &delegated);
21659+ if (delegated) {
21660+ err = break_deleg_wait(&delegated);
21661+ if (!err)
21662+ continue;
21663+ }
21664+ break;
21665+ }
21666+ }
8cdd5066
JR
21667+ /*
21668+ * regardless aufs 'acl' option setting.
21669+ * why don't all acl-aware fs call this func from their ->setattr()?
21670+ */
21671+ if (!err && (ia->ia_valid & ATTR_MODE))
21672+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode);
4a4d8108
AM
21673+ if (!err)
21674+ au_cpup_attr_changeable(inode);
1308ab2a 21675+
4f0767ce 21676+out_unlock:
febd17d6 21677+ inode_unlock(a->h_inode);
4a4d8108 21678+ au_unpin(&a->pin);
027c5e7a 21679+ if (unlikely(err))
5afbbe0d 21680+ au_update_dbtop(dentry);
4f0767ce 21681+out_dentry:
4a4d8108
AM
21682+ di_write_unlock(dentry);
21683+ if (file) {
21684+ fi_write_unlock(file);
21685+ ia->ia_file = file;
21686+ ia->ia_valid |= ATTR_FILE;
21687+ }
4f0767ce 21688+out_si:
4a4d8108 21689+ si_read_unlock(sb);
e49829fe 21690+out_kfree:
9f237c51 21691+ au_kfree_rcu(a);
4f0767ce 21692+out:
4a4d8108
AM
21693+ AuTraceErr(err);
21694+ return err;
1facf9fc 21695+}
21696+
c1595e42
JR
21697+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
21698+static int au_h_path_to_set_attr(struct dentry *dentry,
21699+ struct au_icpup_args *a, struct path *h_path)
21700+{
21701+ int err;
21702+ struct super_block *sb;
21703+
21704+ sb = dentry->d_sb;
21705+ a->udba = au_opt_udba(sb);
21706+ /* no d_unlinked(), to set UDBA_NONE for root */
21707+ if (d_unhashed(dentry))
21708+ a->udba = AuOpt_UDBA_NONE;
21709+ if (a->udba != AuOpt_UDBA_NONE) {
21710+ AuDebugOn(IS_ROOT(dentry));
21711+ err = au_reval_for_attr(dentry, au_sigen(sb));
21712+ if (unlikely(err))
21713+ goto out;
21714+ }
21715+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a);
21716+ if (unlikely(err < 0))
21717+ goto out;
21718+
21719+ h_path->dentry = a->h_path.dentry;
21720+ h_path->mnt = au_sbr_mnt(sb, a->btgt);
21721+
21722+out:
21723+ return err;
21724+}
21725+
f2c43d5f
AM
21726+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
21727+ struct au_sxattr *arg)
c1595e42
JR
21728+{
21729+ int err;
21730+ struct path h_path;
21731+ struct super_block *sb;
21732+ struct au_icpup_args *a;
5afbbe0d 21733+ struct inode *h_inode;
c1595e42 21734+
c1595e42
JR
21735+ IMustLock(inode);
21736+
21737+ err = -ENOMEM;
21738+ a = kzalloc(sizeof(*a), GFP_NOFS);
21739+ if (unlikely(!a))
21740+ goto out;
21741+
21742+ sb = dentry->d_sb;
21743+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21744+ if (unlikely(err))
21745+ goto out_kfree;
21746+
21747+ h_path.dentry = NULL; /* silence gcc */
21748+ di_write_lock_child(dentry);
21749+ err = au_h_path_to_set_attr(dentry, a, &h_path);
21750+ if (unlikely(err))
21751+ goto out_di;
21752+
febd17d6 21753+ inode_unlock(a->h_inode);
c1595e42
JR
21754+ switch (arg->type) {
21755+ case AU_XATTR_SET:
5afbbe0d 21756+ AuDebugOn(d_is_negative(h_path.dentry));
c1595e42
JR
21757+ err = vfsub_setxattr(h_path.dentry,
21758+ arg->u.set.name, arg->u.set.value,
21759+ arg->u.set.size, arg->u.set.flags);
21760+ break;
c1595e42
JR
21761+ case AU_ACL_SET:
21762+ err = -EOPNOTSUPP;
5527c038 21763+ h_inode = d_inode(h_path.dentry);
c1595e42 21764+ if (h_inode->i_op->set_acl)
f2c43d5f 21765+ /* this will call posix_acl_update_mode */
c1595e42
JR
21766+ err = h_inode->i_op->set_acl(h_inode,
21767+ arg->u.acl_set.acl,
21768+ arg->u.acl_set.type);
21769+ break;
21770+ }
21771+ if (!err)
21772+ au_cpup_attr_timesizes(inode);
21773+
21774+ au_unpin(&a->pin);
21775+ if (unlikely(err))
5afbbe0d 21776+ au_update_dbtop(dentry);
c1595e42
JR
21777+
21778+out_di:
21779+ di_write_unlock(dentry);
21780+ si_read_unlock(sb);
21781+out_kfree:
9f237c51 21782+ au_kfree_rcu(a);
c1595e42
JR
21783+out:
21784+ AuTraceErr(err);
21785+ return err;
21786+}
21787+#endif
21788+
4a4d8108
AM
21789+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
21790+ unsigned int nlink)
1facf9fc 21791+{
9dbd164d
AM
21792+ unsigned int n;
21793+
4a4d8108 21794+ inode->i_mode = st->mode;
86dc4139
AM
21795+ /* don't i_[ug]id_write() here */
21796+ inode->i_uid = st->uid;
21797+ inode->i_gid = st->gid;
4a4d8108
AM
21798+ inode->i_atime = st->atime;
21799+ inode->i_mtime = st->mtime;
21800+ inode->i_ctime = st->ctime;
1facf9fc 21801+
4a4d8108
AM
21802+ au_cpup_attr_nlink(inode, /*force*/0);
21803+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
21804+ n = inode->i_nlink;
21805+ n -= nlink;
21806+ n += st->nlink;
f6b6e03d 21807+ smp_mb(); /* for i_nlink */
7eafdf33 21808+ /* 0 can happen */
92d182d2 21809+ set_nlink(inode, n);
4a4d8108 21810+ }
1facf9fc 21811+
4a4d8108
AM
21812+ spin_lock(&inode->i_lock);
21813+ inode->i_blocks = st->blocks;
21814+ i_size_write(inode, st->size);
21815+ spin_unlock(&inode->i_lock);
1facf9fc 21816+}
21817+
c1595e42 21818+/*
f2c43d5f 21819+ * common routine for aufs_getattr() and au_getxattr().
c1595e42
JR
21820+ * returns zero or negative (an error).
21821+ * @dentry will be read-locked in success.
21822+ */
a2654f78
AM
21823+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
21824+ int locked)
1facf9fc 21825+{
4a4d8108 21826+ int err;
076b876e 21827+ unsigned int mnt_flags, sigen;
c1595e42 21828+ unsigned char udba_none;
4a4d8108 21829+ aufs_bindex_t bindex;
4a4d8108
AM
21830+ struct super_block *sb, *h_sb;
21831+ struct inode *inode;
1facf9fc 21832+
c1595e42
JR
21833+ h_path->mnt = NULL;
21834+ h_path->dentry = NULL;
21835+
21836+ err = 0;
4a4d8108 21837+ sb = dentry->d_sb;
4a4d8108
AM
21838+ mnt_flags = au_mntflags(sb);
21839+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 21840+
a2654f78
AM
21841+ if (unlikely(locked))
21842+ goto body; /* skip locking dinfo */
21843+
4a4d8108 21844+ /* support fstat(2) */
027c5e7a 21845+ if (!d_unlinked(dentry) && !udba_none) {
076b876e 21846+ sigen = au_sigen(sb);
027c5e7a
AM
21847+ err = au_digen_test(dentry, sigen);
21848+ if (!err) {
4a4d8108 21849+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a 21850+ err = au_dbrange_test(dentry);
c1595e42
JR
21851+ if (unlikely(err)) {
21852+ di_read_unlock(dentry, AuLock_IR);
21853+ goto out;
21854+ }
027c5e7a 21855+ } else {
4a4d8108
AM
21856+ AuDebugOn(IS_ROOT(dentry));
21857+ di_write_lock_child(dentry);
027c5e7a
AM
21858+ err = au_dbrange_test(dentry);
21859+ if (!err)
21860+ err = au_reval_for_attr(dentry, sigen);
c1595e42
JR
21861+ if (!err)
21862+ di_downgrade_lock(dentry, AuLock_IR);
21863+ else {
21864+ di_write_unlock(dentry);
21865+ goto out;
21866+ }
4a4d8108
AM
21867+ }
21868+ } else
21869+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 21870+
a2654f78 21871+body:
5527c038 21872+ inode = d_inode(dentry);
5afbbe0d 21873+ bindex = au_ibtop(inode);
c1595e42
JR
21874+ h_path->mnt = au_sbr_mnt(sb, bindex);
21875+ h_sb = h_path->mnt->mnt_sb;
21876+ if (!force
21877+ && !au_test_fs_bad_iattr(h_sb)
21878+ && udba_none)
21879+ goto out; /* success */
1facf9fc 21880+
5afbbe0d 21881+ if (au_dbtop(dentry) == bindex)
c1595e42 21882+ h_path->dentry = au_h_dptr(dentry, bindex);
4a4d8108 21883+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
c1595e42
JR
21884+ h_path->dentry = au_plink_lkup(inode, bindex);
21885+ if (IS_ERR(h_path->dentry))
21886+ /* pretending success */
21887+ h_path->dentry = NULL;
21888+ else
21889+ dput(h_path->dentry);
4a4d8108 21890+ }
c1595e42
JR
21891+
21892+out:
21893+ return err;
21894+}
21895+
521ced18
JR
21896+static int aufs_getattr(const struct path *path, struct kstat *st,
21897+ u32 request, unsigned int query)
c1595e42
JR
21898+{
21899+ int err;
21900+ unsigned char positive;
21901+ struct path h_path;
521ced18 21902+ struct dentry *dentry;
c1595e42
JR
21903+ struct inode *inode;
21904+ struct super_block *sb;
21905+
521ced18 21906+ dentry = path->dentry;
5527c038 21907+ inode = d_inode(dentry);
c1595e42
JR
21908+ sb = dentry->d_sb;
21909+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21910+ if (unlikely(err))
21911+ goto out;
a2654f78 21912+ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0);
c1595e42
JR
21913+ if (unlikely(err))
21914+ goto out_si;
c06a8ce3 21915+ if (unlikely(!h_path.dentry))
c1595e42 21916+ /* illegally overlapped or something */
4a4d8108
AM
21917+ goto out_fill; /* pretending success */
21918+
5527c038 21919+ positive = d_is_positive(h_path.dentry);
4a4d8108 21920+ if (positive)
521ced18
JR
21921+ /* no vfsub version */
21922+ err = vfs_getattr(&h_path, st, request, query);
4a4d8108
AM
21923+ if (!err) {
21924+ if (positive)
c06a8ce3 21925+ au_refresh_iattr(inode, st,
5527c038 21926+ d_inode(h_path.dentry)->i_nlink);
4a4d8108 21927+ goto out_fill; /* success */
1facf9fc 21928+ }
7f207e10 21929+ AuTraceErr(err);
c1595e42 21930+ goto out_di;
4a4d8108 21931+
4f0767ce 21932+out_fill:
4a4d8108 21933+ generic_fillattr(inode, st);
c1595e42 21934+out_di:
4a4d8108 21935+ di_read_unlock(dentry, AuLock_IR);
c1595e42 21936+out_si:
4a4d8108 21937+ si_read_unlock(sb);
7f207e10
AM
21938+out:
21939+ AuTraceErr(err);
4a4d8108 21940+ return err;
1facf9fc 21941+}
21942+
21943+/* ---------------------------------------------------------------------- */
21944+
febd17d6
JR
21945+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode,
21946+ struct delayed_call *done)
4a4d8108 21947+{
c2c0f25c 21948+ const char *ret;
c2c0f25c 21949+ struct dentry *h_dentry;
febd17d6 21950+ struct inode *h_inode;
4a4d8108 21951+ int err;
c2c0f25c 21952+ aufs_bindex_t bindex;
1facf9fc 21953+
79b8bda9 21954+ ret = NULL; /* suppress a warning */
febd17d6
JR
21955+ err = -ECHILD;
21956+ if (!dentry)
21957+ goto out;
21958+
027c5e7a
AM
21959+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
21960+ if (unlikely(err))
c2c0f25c 21961+ goto out;
027c5e7a
AM
21962+
21963+ err = au_d_hashed_positive(dentry);
c2c0f25c
AM
21964+ if (unlikely(err))
21965+ goto out_unlock;
21966+
21967+ err = -EINVAL;
21968+ inode = d_inode(dentry);
5afbbe0d 21969+ bindex = au_ibtop(inode);
c2c0f25c 21970+ h_inode = au_h_iptr(inode, bindex);
febd17d6 21971+ if (unlikely(!h_inode->i_op->get_link))
c2c0f25c
AM
21972+ goto out_unlock;
21973+
21974+ err = -EBUSY;
21975+ h_dentry = NULL;
5afbbe0d 21976+ if (au_dbtop(dentry) <= bindex) {
c2c0f25c
AM
21977+ h_dentry = au_h_dptr(dentry, bindex);
21978+ if (h_dentry)
21979+ dget(h_dentry);
027c5e7a 21980+ }
c2c0f25c
AM
21981+ if (!h_dentry) {
21982+ h_dentry = d_find_any_alias(h_inode);
21983+ if (IS_ERR(h_dentry)) {
21984+ err = PTR_ERR(h_dentry);
febd17d6 21985+ goto out_unlock;
c2c0f25c
AM
21986+ }
21987+ }
21988+ if (unlikely(!h_dentry))
febd17d6 21989+ goto out_unlock;
1facf9fc 21990+
c2c0f25c 21991+ err = 0;
062440b3 21992+ AuDbg("%ps\n", h_inode->i_op->get_link);
c2c0f25c 21993+ AuDbgDentry(h_dentry);
f2c43d5f 21994+ ret = vfs_get_link(h_dentry, done);
c2c0f25c 21995+ dput(h_dentry);
febd17d6
JR
21996+ if (IS_ERR(ret))
21997+ err = PTR_ERR(ret);
c2c0f25c 21998+
c2c0f25c
AM
21999+out_unlock:
22000+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 22001+out:
c2c0f25c
AM
22002+ if (unlikely(err))
22003+ ret = ERR_PTR(err);
22004+ AuTraceErrPtr(ret);
22005+ return ret;
4a4d8108 22006+}
1facf9fc 22007+
4a4d8108 22008+/* ---------------------------------------------------------------------- */
1facf9fc 22009+
e2f27e51
AM
22010+static int au_is_special(struct inode *inode)
22011+{
22012+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK));
22013+}
22014+
acd2b654
AM
22015+static int aufs_update_time(struct inode *inode, struct timespec64 *ts,
22016+ int flags)
4a4d8108 22017+{
0c3ec466 22018+ int err;
e2f27e51 22019+ aufs_bindex_t bindex;
0c3ec466
AM
22020+ struct super_block *sb;
22021+ struct inode *h_inode;
e2f27e51 22022+ struct vfsmount *h_mnt;
0c3ec466
AM
22023+
22024+ sb = inode->i_sb;
e2f27e51
AM
22025+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode),
22026+ "unexpected s_flags 0x%lx", sb->s_flags);
22027+
0c3ec466
AM
22028+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
22029+ lockdep_off();
22030+ si_read_lock(sb, AuLock_FLUSH);
22031+ ii_write_lock_child(inode);
e2f27e51
AM
22032+
22033+ err = 0;
22034+ bindex = au_ibtop(inode);
22035+ h_inode = au_h_iptr(inode, bindex);
22036+ if (!au_test_ro(sb, bindex, inode)) {
22037+ h_mnt = au_sbr_mnt(sb, bindex);
22038+ err = vfsub_mnt_want_write(h_mnt);
22039+ if (!err) {
22040+ err = vfsub_update_time(h_inode, ts, flags);
22041+ vfsub_mnt_drop_write(h_mnt);
22042+ }
22043+ } else if (au_is_special(h_inode)) {
22044+ /*
22045+ * Never copy-up here.
22046+ * These special files may already be opened and used for
22047+ * communicating. If we copied it up, then the communication
22048+ * would be corrupted.
22049+ */
22050+ AuWarn1("timestamps for i%lu are ignored "
22051+ "since it is on readonly branch (hi%lu).\n",
22052+ inode->i_ino, h_inode->i_ino);
22053+ } else if (flags & ~S_ATIME) {
22054+ err = -EIO;
22055+ AuIOErr1("unexpected flags 0x%x\n", flags);
22056+ AuDebugOn(1);
22057+ }
22058+
38d290e6
JR
22059+ if (!err)
22060+ au_cpup_attr_timesizes(inode);
0c3ec466
AM
22061+ ii_write_unlock(inode);
22062+ si_read_unlock(sb);
22063+ lockdep_on();
38d290e6
JR
22064+
22065+ if (!err && (flags & S_VERSION))
22066+ inode_inc_iversion(inode);
22067+
0c3ec466 22068+ return err;
4a4d8108 22069+}
1facf9fc 22070+
4a4d8108 22071+/* ---------------------------------------------------------------------- */
1308ab2a 22072+
b95c5147
AM
22073+/* no getattr version will be set by module.c:aufs_init() */
22074+struct inode_operations aufs_iop_nogetattr[AuIop_Last],
22075+ aufs_iop[] = {
22076+ [AuIop_SYMLINK] = {
22077+ .permission = aufs_permission,
c1595e42 22078+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22079+ .get_acl = aufs_get_acl,
22080+ .set_acl = aufs_set_acl, /* unsupport for symlink? */
c1595e42
JR
22081+#endif
22082+
b95c5147
AM
22083+ .setattr = aufs_setattr,
22084+ .getattr = aufs_getattr,
0c3ec466 22085+
c1595e42 22086+#ifdef CONFIG_AUFS_XATTR
b95c5147 22087+ .listxattr = aufs_listxattr,
c1595e42
JR
22088+#endif
22089+
febd17d6 22090+ .get_link = aufs_get_link,
0c3ec466 22091+
b95c5147
AM
22092+ /* .update_time = aufs_update_time */
22093+ },
22094+ [AuIop_DIR] = {
22095+ .create = aufs_create,
22096+ .lookup = aufs_lookup,
22097+ .link = aufs_link,
22098+ .unlink = aufs_unlink,
22099+ .symlink = aufs_symlink,
22100+ .mkdir = aufs_mkdir,
22101+ .rmdir = aufs_rmdir,
22102+ .mknod = aufs_mknod,
22103+ .rename = aufs_rename,
22104+
22105+ .permission = aufs_permission,
c1595e42 22106+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22107+ .get_acl = aufs_get_acl,
22108+ .set_acl = aufs_set_acl,
c1595e42
JR
22109+#endif
22110+
b95c5147
AM
22111+ .setattr = aufs_setattr,
22112+ .getattr = aufs_getattr,
0c3ec466 22113+
c1595e42 22114+#ifdef CONFIG_AUFS_XATTR
b95c5147 22115+ .listxattr = aufs_listxattr,
c1595e42
JR
22116+#endif
22117+
b95c5147
AM
22118+ .update_time = aufs_update_time,
22119+ .atomic_open = aufs_atomic_open,
22120+ .tmpfile = aufs_tmpfile
22121+ },
22122+ [AuIop_OTHER] = {
22123+ .permission = aufs_permission,
c1595e42 22124+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22125+ .get_acl = aufs_get_acl,
22126+ .set_acl = aufs_set_acl,
c1595e42
JR
22127+#endif
22128+
b95c5147
AM
22129+ .setattr = aufs_setattr,
22130+ .getattr = aufs_getattr,
0c3ec466 22131+
c1595e42 22132+#ifdef CONFIG_AUFS_XATTR
b95c5147 22133+ .listxattr = aufs_listxattr,
c1595e42
JR
22134+#endif
22135+
b95c5147
AM
22136+ .update_time = aufs_update_time
22137+ }
4a4d8108 22138+};
7f207e10 22139diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
fbc438ed
JR
22140--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 08:00:00.000000000 +0800
22141+++ linux/fs/aufs/i_op_del.c 2019-07-11 21:21:54.382384486 +0800
eca801bf 22142@@ -0,0 +1,513 @@
cd7a4cd9 22143+// SPDX-License-Identifier: GPL-2.0
1facf9fc 22144+/*
ba1aed25 22145+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 22146+ *
22147+ * This program, aufs is free software; you can redistribute it and/or modify
22148+ * it under the terms of the GNU General Public License as published by
22149+ * the Free Software Foundation; either version 2 of the License, or
22150+ * (at your option) any later version.
dece6358
AM
22151+ *
22152+ * This program is distributed in the hope that it will be useful,
22153+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22154+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22155+ * GNU General Public License for more details.
22156+ *
22157+ * You should have received a copy of the GNU General Public License
523b37e3 22158+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22159+ */
22160+
22161+/*
4a4d8108 22162+ * inode operations (del entry)
1308ab2a 22163+ */
dece6358 22164+
eca801bf 22165+#include <linux/iversion.h>
1308ab2a 22166+#include "aufs.h"
dece6358 22167+
4a4d8108
AM
22168+/*
22169+ * decide if a new whiteout for @dentry is necessary or not.
22170+ * when it is necessary, prepare the parent dir for the upper branch whose
22171+ * branch index is @bcpup for creation. the actual creation of the whiteout will
22172+ * be done by caller.
22173+ * return value:
22174+ * 0: wh is unnecessary
22175+ * plus: wh is necessary
22176+ * minus: error
22177+ */
22178+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 22179+{
4a4d8108 22180+ int need_wh, err;
5afbbe0d 22181+ aufs_bindex_t btop;
4a4d8108 22182+ struct super_block *sb;
dece6358 22183+
4a4d8108 22184+ sb = dentry->d_sb;
5afbbe0d 22185+ btop = au_dbtop(dentry);
4a4d8108 22186+ if (*bcpup < 0) {
5afbbe0d
AM
22187+ *bcpup = btop;
22188+ if (au_test_ro(sb, btop, d_inode(dentry))) {
4a4d8108
AM
22189+ err = AuWbrCopyup(au_sbi(sb), dentry);
22190+ *bcpup = err;
22191+ if (unlikely(err < 0))
22192+ goto out;
22193+ }
22194+ } else
5afbbe0d 22195+ AuDebugOn(btop < *bcpup
5527c038 22196+ || au_test_ro(sb, *bcpup, d_inode(dentry)));
5afbbe0d 22197+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop);
1308ab2a 22198+
5afbbe0d 22199+ if (*bcpup != btop) {
4a4d8108
AM
22200+ err = au_cpup_dirs(dentry, *bcpup);
22201+ if (unlikely(err))
22202+ goto out;
22203+ need_wh = 1;
22204+ } else {
027c5e7a 22205+ struct au_dinfo *dinfo, *tmp;
4a4d8108 22206+
027c5e7a
AM
22207+ need_wh = -ENOMEM;
22208+ dinfo = au_di(dentry);
22209+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
22210+ if (tmp) {
22211+ au_di_cp(tmp, dinfo);
22212+ au_di_swap(tmp, dinfo);
22213+ /* returns the number of positive dentries */
5afbbe0d
AM
22214+ need_wh = au_lkup_dentry(dentry, btop + 1,
22215+ /* AuLkup_IGNORE_PERM */ 0);
027c5e7a
AM
22216+ au_di_swap(tmp, dinfo);
22217+ au_rw_write_unlock(&tmp->di_rwsem);
22218+ au_di_free(tmp);
4a4d8108
AM
22219+ }
22220+ }
22221+ AuDbg("need_wh %d\n", need_wh);
22222+ err = need_wh;
22223+
4f0767ce 22224+out:
4a4d8108 22225+ return err;
1facf9fc 22226+}
22227+
4a4d8108
AM
22228+/*
22229+ * simple tests for the del-entry operations.
22230+ * following the checks in vfs, plus the parent-child relationship.
22231+ */
22232+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
22233+ struct dentry *h_parent, int isdir)
1facf9fc 22234+{
4a4d8108
AM
22235+ int err;
22236+ umode_t h_mode;
22237+ struct dentry *h_dentry, *h_latest;
1308ab2a 22238+ struct inode *h_inode;
1facf9fc 22239+
4a4d8108 22240+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 22241+ if (d_really_is_positive(dentry)) {
4a4d8108 22242+ err = -ENOENT;
5527c038
JR
22243+ if (unlikely(d_is_negative(h_dentry)))
22244+ goto out;
22245+ h_inode = d_inode(h_dentry);
22246+ if (unlikely(!h_inode->i_nlink))
4a4d8108 22247+ goto out;
1facf9fc 22248+
4a4d8108
AM
22249+ h_mode = h_inode->i_mode;
22250+ if (!isdir) {
22251+ err = -EISDIR;
22252+ if (unlikely(S_ISDIR(h_mode)))
22253+ goto out;
22254+ } else if (unlikely(!S_ISDIR(h_mode))) {
22255+ err = -ENOTDIR;
22256+ goto out;
22257+ }
22258+ } else {
22259+ /* rename(2) case */
22260+ err = -EIO;
5527c038 22261+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
22262+ goto out;
22263+ }
1facf9fc 22264+
4a4d8108
AM
22265+ err = -ENOENT;
22266+ /* expected parent dir is locked */
22267+ if (unlikely(h_parent != h_dentry->d_parent))
22268+ goto out;
22269+ err = 0;
22270+
22271+ /*
22272+ * rmdir a dir may break the consistency on some filesystem.
22273+ * let's try heavy test.
22274+ */
22275+ err = -EACCES;
076b876e 22276+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
5527c038 22277+ && au_test_h_perm(d_inode(h_parent),
076b876e 22278+ MAY_EXEC | MAY_WRITE)))
4a4d8108
AM
22279+ goto out;
22280+
076b876e 22281+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent);
4a4d8108
AM
22282+ err = -EIO;
22283+ if (IS_ERR(h_latest))
22284+ goto out;
22285+ if (h_latest == h_dentry)
22286+ err = 0;
22287+ dput(h_latest);
22288+
4f0767ce 22289+out:
4a4d8108 22290+ return err;
1308ab2a 22291+}
1facf9fc 22292+
4a4d8108
AM
22293+/*
22294+ * decide the branch where we operate for @dentry. the branch index will be set
acd2b654 22295+ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent
4a4d8108
AM
22296+ * dir for reverting.
22297+ * when a new whiteout is necessary, create it.
22298+ */
22299+static struct dentry*
22300+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
22301+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 22302+{
4a4d8108
AM
22303+ struct dentry *wh_dentry;
22304+ struct super_block *sb;
22305+ struct path h_path;
22306+ int err, need_wh;
22307+ unsigned int udba;
22308+ aufs_bindex_t bcpup;
dece6358 22309+
4a4d8108
AM
22310+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
22311+ wh_dentry = ERR_PTR(need_wh);
22312+ if (unlikely(need_wh < 0))
22313+ goto out;
22314+
22315+ sb = dentry->d_sb;
22316+ udba = au_opt_udba(sb);
22317+ bcpup = *rbcpup;
22318+ err = au_pin(pin, dentry, bcpup, udba,
22319+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
22320+ wh_dentry = ERR_PTR(err);
22321+ if (unlikely(err))
22322+ goto out;
22323+
22324+ h_path.dentry = au_pinned_h_parent(pin);
22325+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 22326+ && au_dbtop(dentry) == bcpup) {
4a4d8108
AM
22327+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
22328+ wh_dentry = ERR_PTR(err);
22329+ if (unlikely(err))
22330+ goto out_unpin;
22331+ }
22332+
22333+ h_path.mnt = au_sbr_mnt(sb, bcpup);
22334+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
22335+ wh_dentry = NULL;
22336+ if (!need_wh)
22337+ goto out; /* success, no need to create whiteout */
22338+
22339+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
22340+ if (IS_ERR(wh_dentry))
22341+ goto out_unpin;
22342+
22343+ /* returns with the parent is locked and wh_dentry is dget-ed */
22344+ goto out; /* success */
22345+
4f0767ce 22346+out_unpin:
4a4d8108 22347+ au_unpin(pin);
4f0767ce 22348+out:
4a4d8108 22349+ return wh_dentry;
1facf9fc 22350+}
22351+
4a4d8108
AM
22352+/*
22353+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
22354+ * in order to be revertible and save time for removing many child whiteouts
22355+ * under the dir.
22356+ * returns 1 when there are too many child whiteout and caller should remove
22357+ * them asynchronously. returns 0 when the number of children is enough small to
22358+ * remove now or the branch fs is a remote fs.
22359+ * otherwise return an error.
22360+ */
22361+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
22362+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 22363+{
4a4d8108
AM
22364+ int rmdir_later, err, dirwh;
22365+ struct dentry *h_dentry;
22366+ struct super_block *sb;
5527c038 22367+ struct inode *inode;
4a4d8108
AM
22368+
22369+ sb = dentry->d_sb;
22370+ SiMustAnyLock(sb);
22371+ h_dentry = au_h_dptr(dentry, bindex);
22372+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
22373+ if (unlikely(err))
22374+ goto out;
22375+
22376+ /* stop monitoring */
5527c038
JR
22377+ inode = d_inode(dentry);
22378+ au_hn_free(au_hi(inode, bindex));
4a4d8108
AM
22379+
22380+ if (!au_test_fs_remote(h_dentry->d_sb)) {
22381+ dirwh = au_sbi(sb)->si_dirwh;
22382+ rmdir_later = (dirwh <= 1);
22383+ if (!rmdir_later)
22384+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
22385+ dirwh);
22386+ if (rmdir_later)
22387+ return rmdir_later;
22388+ }
1facf9fc 22389+
4a4d8108
AM
22390+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
22391+ if (unlikely(err)) {
523b37e3
AM
22392+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n",
22393+ h_dentry, bindex, err);
4a4d8108
AM
22394+ err = 0;
22395+ }
dece6358 22396+
4f0767ce 22397+out:
4a4d8108
AM
22398+ AuTraceErr(err);
22399+ return err;
22400+}
1308ab2a 22401+
4a4d8108
AM
22402+/*
22403+ * final procedure for deleting a entry.
22404+ * maintain dentry and iattr.
22405+ */
22406+static void epilog(struct inode *dir, struct dentry *dentry,
22407+ aufs_bindex_t bindex)
22408+{
22409+ struct inode *inode;
1308ab2a 22410+
5527c038 22411+ inode = d_inode(dentry);
4a4d8108
AM
22412+ d_drop(dentry);
22413+ inode->i_ctime = dir->i_ctime;
1308ab2a 22414+
b912730e 22415+ au_dir_ts(dir, bindex);
be118d29 22416+ inode_inc_iversion(dir);
1facf9fc 22417+}
22418+
4a4d8108
AM
22419+/*
22420+ * when an error happened, remove the created whiteout and revert everything.
22421+ */
7f207e10
AM
22422+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
22423+ aufs_bindex_t bwh, struct dentry *wh_dentry,
22424+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 22425+{
4a4d8108
AM
22426+ int rerr;
22427+ struct path h_path = {
22428+ .dentry = wh_dentry,
7f207e10 22429+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 22430+ };
dece6358 22431+
7f207e10 22432+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
22433+ if (!rerr) {
22434+ au_set_dbwh(dentry, bwh);
22435+ au_dtime_revert(dt);
22436+ return 0;
22437+ }
dece6358 22438+
523b37e3 22439+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr);
4a4d8108 22440+ return -EIO;
1facf9fc 22441+}
22442+
4a4d8108 22443+/* ---------------------------------------------------------------------- */
1facf9fc 22444+
4a4d8108 22445+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 22446+{
4a4d8108 22447+ int err;
5afbbe0d 22448+ aufs_bindex_t bwh, bindex, btop;
523b37e3 22449+ struct inode *inode, *h_dir, *delegated;
4a4d8108 22450+ struct dentry *parent, *wh_dentry;
acd2b654 22451+ /* to reduce stack size */
c2b27bf2
AM
22452+ struct {
22453+ struct au_dtime dt;
22454+ struct au_pin pin;
22455+ struct path h_path;
22456+ } *a;
1facf9fc 22457+
4a4d8108 22458+ IMustLock(dir);
027c5e7a 22459+
c2b27bf2
AM
22460+ err = -ENOMEM;
22461+ a = kmalloc(sizeof(*a), GFP_NOFS);
22462+ if (unlikely(!a))
22463+ goto out;
22464+
027c5e7a
AM
22465+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
22466+ if (unlikely(err))
c2b27bf2 22467+ goto out_free;
027c5e7a
AM
22468+ err = au_d_hashed_positive(dentry);
22469+ if (unlikely(err))
22470+ goto out_unlock;
5527c038 22471+ inode = d_inode(dentry);
4a4d8108 22472+ IMustLock(inode);
027c5e7a 22473+ err = -EISDIR;
2000de60 22474+ if (unlikely(d_is_dir(dentry)))
027c5e7a 22475+ goto out_unlock; /* possible? */
1facf9fc 22476+
5afbbe0d 22477+ btop = au_dbtop(dentry);
4a4d8108
AM
22478+ bwh = au_dbwh(dentry);
22479+ bindex = -1;
027c5e7a
AM
22480+ parent = dentry->d_parent; /* dir inode is locked */
22481+ di_write_lock_parent(parent);
c2b27bf2
AM
22482+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
22483+ &a->pin);
4a4d8108
AM
22484+ err = PTR_ERR(wh_dentry);
22485+ if (IS_ERR(wh_dentry))
027c5e7a 22486+ goto out_parent;
1facf9fc 22487+
5afbbe0d
AM
22488+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop);
22489+ a->h_path.dentry = au_h_dptr(dentry, btop);
c2b27bf2 22490+ dget(a->h_path.dentry);
5afbbe0d 22491+ if (bindex == btop) {
c2b27bf2 22492+ h_dir = au_pinned_h_dir(&a->pin);
523b37e3
AM
22493+ delegated = NULL;
22494+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0);
22495+ if (unlikely(err == -EWOULDBLOCK)) {
22496+ pr_warn("cannot retry for NFSv4 delegation"
22497+ " for an internal unlink\n");
22498+ iput(delegated);
22499+ }
4a4d8108
AM
22500+ } else {
22501+ /* dir inode is locked */
5527c038 22502+ h_dir = d_inode(wh_dentry->d_parent);
4a4d8108
AM
22503+ IMustLock(h_dir);
22504+ err = 0;
22505+ }
dece6358 22506+
4a4d8108 22507+ if (!err) {
7f207e10 22508+ vfsub_drop_nlink(inode);
4a4d8108
AM
22509+ epilog(dir, dentry, bindex);
22510+
22511+ /* update target timestamps */
5afbbe0d 22512+ if (bindex == btop) {
c2b27bf2
AM
22513+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
22514+ /*ignore*/
5527c038 22515+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
4a4d8108
AM
22516+ } else
22517+ /* todo: this timestamp may be reverted later */
22518+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 22519+ goto out_unpin; /* success */
1facf9fc 22520+ }
22521+
4a4d8108
AM
22522+ /* revert */
22523+ if (wh_dentry) {
22524+ int rerr;
22525+
c2b27bf2
AM
22526+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22527+ &a->dt);
4a4d8108
AM
22528+ if (rerr)
22529+ err = rerr;
dece6358 22530+ }
1facf9fc 22531+
027c5e7a 22532+out_unpin:
c2b27bf2 22533+ au_unpin(&a->pin);
4a4d8108 22534+ dput(wh_dentry);
c2b27bf2 22535+ dput(a->h_path.dentry);
027c5e7a 22536+out_parent:
4a4d8108 22537+ di_write_unlock(parent);
027c5e7a 22538+out_unlock:
4a4d8108 22539+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22540+out_free:
9f237c51 22541+ au_kfree_rcu(a);
027c5e7a 22542+out:
4a4d8108 22543+ return err;
dece6358
AM
22544+}
22545+
4a4d8108 22546+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 22547+{
4a4d8108 22548+ int err, rmdir_later;
5afbbe0d 22549+ aufs_bindex_t bwh, bindex, btop;
4a4d8108
AM
22550+ struct inode *inode;
22551+ struct dentry *parent, *wh_dentry, *h_dentry;
22552+ struct au_whtmp_rmdir *args;
acd2b654 22553+ /* to reduce stack size */
c2b27bf2
AM
22554+ struct {
22555+ struct au_dtime dt;
22556+ struct au_pin pin;
22557+ } *a;
1facf9fc 22558+
4a4d8108 22559+ IMustLock(dir);
027c5e7a 22560+
c2b27bf2
AM
22561+ err = -ENOMEM;
22562+ a = kmalloc(sizeof(*a), GFP_NOFS);
22563+ if (unlikely(!a))
22564+ goto out;
22565+
027c5e7a
AM
22566+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
22567+ if (unlikely(err))
c2b27bf2 22568+ goto out_free;
53392da6
AM
22569+ err = au_alive_dir(dentry);
22570+ if (unlikely(err))
027c5e7a 22571+ goto out_unlock;
5527c038 22572+ inode = d_inode(dentry);
4a4d8108 22573+ IMustLock(inode);
027c5e7a 22574+ err = -ENOTDIR;
2000de60 22575+ if (unlikely(!d_is_dir(dentry)))
027c5e7a 22576+ goto out_unlock; /* possible? */
dece6358 22577+
4a4d8108
AM
22578+ err = -ENOMEM;
22579+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
22580+ if (unlikely(!args))
22581+ goto out_unlock;
dece6358 22582+
4a4d8108
AM
22583+ parent = dentry->d_parent; /* dir inode is locked */
22584+ di_write_lock_parent(parent);
22585+ err = au_test_empty(dentry, &args->whlist);
22586+ if (unlikely(err))
027c5e7a 22587+ goto out_parent;
1facf9fc 22588+
5afbbe0d 22589+ btop = au_dbtop(dentry);
4a4d8108
AM
22590+ bwh = au_dbwh(dentry);
22591+ bindex = -1;
c2b27bf2
AM
22592+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
22593+ &a->pin);
4a4d8108
AM
22594+ err = PTR_ERR(wh_dentry);
22595+ if (IS_ERR(wh_dentry))
027c5e7a 22596+ goto out_parent;
1facf9fc 22597+
5afbbe0d 22598+ h_dentry = au_h_dptr(dentry, btop);
4a4d8108
AM
22599+ dget(h_dentry);
22600+ rmdir_later = 0;
5afbbe0d
AM
22601+ if (bindex == btop) {
22602+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir);
4a4d8108
AM
22603+ if (err > 0) {
22604+ rmdir_later = err;
22605+ err = 0;
22606+ }
22607+ } else {
22608+ /* stop monitoring */
5afbbe0d 22609+ au_hn_free(au_hi(inode, btop));
4a4d8108
AM
22610+
22611+ /* dir inode is locked */
5527c038 22612+ IMustLock(d_inode(wh_dentry->d_parent));
1facf9fc 22613+ err = 0;
22614+ }
22615+
4a4d8108 22616+ if (!err) {
027c5e7a 22617+ vfsub_dead_dir(inode);
4a4d8108
AM
22618+ au_set_dbdiropq(dentry, -1);
22619+ epilog(dir, dentry, bindex);
1308ab2a 22620+
4a4d8108 22621+ if (rmdir_later) {
5afbbe0d 22622+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args);
4a4d8108
AM
22623+ args = NULL;
22624+ }
1308ab2a 22625+
4a4d8108 22626+ goto out_unpin; /* success */
1facf9fc 22627+ }
22628+
4a4d8108
AM
22629+ /* revert */
22630+ AuLabel(revert);
22631+ if (wh_dentry) {
22632+ int rerr;
1308ab2a 22633+
c2b27bf2
AM
22634+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22635+ &a->dt);
4a4d8108
AM
22636+ if (rerr)
22637+ err = rerr;
1facf9fc 22638+ }
22639+
4f0767ce 22640+out_unpin:
c2b27bf2 22641+ au_unpin(&a->pin);
4a4d8108
AM
22642+ dput(wh_dentry);
22643+ dput(h_dentry);
027c5e7a 22644+out_parent:
4a4d8108
AM
22645+ di_write_unlock(parent);
22646+ if (args)
22647+ au_whtmp_rmdir_free(args);
4f0767ce 22648+out_unlock:
4a4d8108 22649+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22650+out_free:
9f237c51 22651+ au_kfree_rcu(a);
4f0767ce 22652+out:
4a4d8108
AM
22653+ AuTraceErr(err);
22654+ return err;
dece6358 22655+}
7f207e10 22656diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
fbc438ed
JR
22657--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 08:00:00.000000000 +0800
22658+++ linux/fs/aufs/i_op_ren.c 2019-07-11 21:21:54.382384486 +0800
eca801bf 22659@@ -0,0 +1,1250 @@
cd7a4cd9 22660+// SPDX-License-Identifier: GPL-2.0
1facf9fc 22661+/*
ba1aed25 22662+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 22663+ *
22664+ * This program, aufs is free software; you can redistribute it and/or modify
22665+ * it under the terms of the GNU General Public License as published by
22666+ * the Free Software Foundation; either version 2 of the License, or
22667+ * (at your option) any later version.
dece6358
AM
22668+ *
22669+ * This program is distributed in the hope that it will be useful,
22670+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22671+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22672+ * GNU General Public License for more details.
22673+ *
22674+ * You should have received a copy of the GNU General Public License
523b37e3 22675+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22676+ */
22677+
22678+/*
4a4d8108
AM
22679+ * inode operation (rename entry)
22680+ * todo: this is crazy monster
1facf9fc 22681+ */
22682+
eca801bf 22683+#include <linux/iversion.h>
1facf9fc 22684+#include "aufs.h"
22685+
4a4d8108
AM
22686+enum { AuSRC, AuDST, AuSrcDst };
22687+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 22688+
f2c43d5f
AM
22689+#define AuRen_ISDIR_SRC 1
22690+#define AuRen_ISDIR_DST (1 << 1)
22691+#define AuRen_ISSAMEDIR (1 << 2)
22692+#define AuRen_WHSRC (1 << 3)
22693+#define AuRen_WHDST (1 << 4)
22694+#define AuRen_MNT_WRITE (1 << 5)
22695+#define AuRen_DT_DSTDIR (1 << 6)
22696+#define AuRen_DIROPQ_SRC (1 << 7)
22697+#define AuRen_DIROPQ_DST (1 << 8)
8b6a4947
AM
22698+#define AuRen_DIRREN (1 << 9)
22699+#define AuRen_DROPPED_SRC (1 << 10)
22700+#define AuRen_DROPPED_DST (1 << 11)
4a4d8108 22701+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
22702+#define au_fset_ren(flags, name) \
22703+ do { (flags) |= AuRen_##name; } while (0)
22704+#define au_fclr_ren(flags, name) \
22705+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 22706+
8b6a4947
AM
22707+#ifndef CONFIG_AUFS_DIRREN
22708+#undef AuRen_DIRREN
22709+#define AuRen_DIRREN 0
22710+#endif
22711+
4a4d8108
AM
22712+struct au_ren_args {
22713+ struct {
22714+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
22715+ *wh_dentry;
22716+ struct inode *dir, *inode;
f2c43d5f 22717+ struct au_hinode *hdir, *hinode;
4a4d8108 22718+ struct au_dtime dt[AuParentChild];
f2c43d5f 22719+ aufs_bindex_t btop, bdiropq;
4a4d8108 22720+ } sd[AuSrcDst];
1facf9fc 22721+
4a4d8108
AM
22722+#define src_dentry sd[AuSRC].dentry
22723+#define src_dir sd[AuSRC].dir
22724+#define src_inode sd[AuSRC].inode
22725+#define src_h_dentry sd[AuSRC].h_dentry
22726+#define src_parent sd[AuSRC].parent
22727+#define src_h_parent sd[AuSRC].h_parent
22728+#define src_wh_dentry sd[AuSRC].wh_dentry
22729+#define src_hdir sd[AuSRC].hdir
f2c43d5f 22730+#define src_hinode sd[AuSRC].hinode
4a4d8108
AM
22731+#define src_h_dir sd[AuSRC].hdir->hi_inode
22732+#define src_dt sd[AuSRC].dt
5afbbe0d 22733+#define src_btop sd[AuSRC].btop
f2c43d5f 22734+#define src_bdiropq sd[AuSRC].bdiropq
1facf9fc 22735+
4a4d8108
AM
22736+#define dst_dentry sd[AuDST].dentry
22737+#define dst_dir sd[AuDST].dir
22738+#define dst_inode sd[AuDST].inode
22739+#define dst_h_dentry sd[AuDST].h_dentry
22740+#define dst_parent sd[AuDST].parent
22741+#define dst_h_parent sd[AuDST].h_parent
22742+#define dst_wh_dentry sd[AuDST].wh_dentry
22743+#define dst_hdir sd[AuDST].hdir
f2c43d5f 22744+#define dst_hinode sd[AuDST].hinode
4a4d8108
AM
22745+#define dst_h_dir sd[AuDST].hdir->hi_inode
22746+#define dst_dt sd[AuDST].dt
5afbbe0d 22747+#define dst_btop sd[AuDST].btop
f2c43d5f 22748+#define dst_bdiropq sd[AuDST].bdiropq
4a4d8108
AM
22749+
22750+ struct dentry *h_trap;
22751+ struct au_branch *br;
4a4d8108
AM
22752+ struct path h_path;
22753+ struct au_nhash whlist;
f2c43d5f 22754+ aufs_bindex_t btgt, src_bwh;
1facf9fc 22755+
f2c43d5f
AM
22756+ struct {
22757+ unsigned short auren_flags;
22758+ unsigned char flags; /* syscall parameter */
22759+ unsigned char exchange;
22760+ } __packed;
1facf9fc 22761+
4a4d8108
AM
22762+ struct au_whtmp_rmdir *thargs;
22763+ struct dentry *h_dst;
8b6a4947 22764+ struct au_hinode *h_root;
4a4d8108 22765+};
1308ab2a 22766+
4a4d8108 22767+/* ---------------------------------------------------------------------- */
1308ab2a 22768+
4a4d8108
AM
22769+/*
22770+ * functions for reverting.
22771+ * when an error happened in a single rename systemcall, we should revert
79b8bda9 22772+ * everything as if nothing happened.
4a4d8108
AM
22773+ * we don't need to revert the copied-up/down the parent dir since they are
22774+ * harmless.
22775+ */
1facf9fc 22776+
4a4d8108
AM
22777+#define RevertFailure(fmt, ...) do { \
22778+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
22779+ ##__VA_ARGS__, err, rerr); \
22780+ err = -EIO; \
22781+} while (0)
1facf9fc 22782+
f2c43d5f 22783+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx)
1facf9fc 22784+{
4a4d8108 22785+ int rerr;
f2c43d5f
AM
22786+ struct dentry *d;
22787+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22788+
f2c43d5f
AM
22789+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22790+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22791+ rerr = au_diropq_remove(d, a->btgt);
22792+ au_hn_inode_unlock(src_or_dst(hinode));
22793+ au_set_dbdiropq(d, src_or_dst(bdiropq));
4a4d8108 22794+ if (rerr)
f2c43d5f
AM
22795+ RevertFailure("remove diropq %pd", d);
22796+
22797+#undef src_or_dst_
22798+}
22799+
22800+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
22801+{
22802+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC))
22803+ au_ren_do_rev_diropq(err, a, AuSRC);
22804+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST))
22805+ au_ren_do_rev_diropq(err, a, AuDST);
4a4d8108 22806+}
1facf9fc 22807+
4a4d8108
AM
22808+static void au_ren_rev_rename(int err, struct au_ren_args *a)
22809+{
22810+ int rerr;
523b37e3 22811+ struct inode *delegated;
1facf9fc 22812+
b4510431
AM
22813+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
22814+ a->src_h_parent);
4a4d8108
AM
22815+ rerr = PTR_ERR(a->h_path.dentry);
22816+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22817+ RevertFailure("lkup one %pd", a->src_dentry);
4a4d8108 22818+ return;
1facf9fc 22819+ }
22820+
523b37e3 22821+ delegated = NULL;
4a4d8108
AM
22822+ rerr = vfsub_rename(a->dst_h_dir,
22823+ au_h_dptr(a->src_dentry, a->btgt),
f2c43d5f 22824+ a->src_h_dir, &a->h_path, &delegated, a->flags);
523b37e3
AM
22825+ if (unlikely(rerr == -EWOULDBLOCK)) {
22826+ pr_warn("cannot retry for NFSv4 delegation"
22827+ " for an internal rename\n");
22828+ iput(delegated);
22829+ }
4a4d8108
AM
22830+ d_drop(a->h_path.dentry);
22831+ dput(a->h_path.dentry);
22832+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
22833+ if (rerr)
523b37e3 22834+ RevertFailure("rename %pd", a->src_dentry);
1facf9fc 22835+}
22836+
4a4d8108 22837+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 22838+{
4a4d8108 22839+ int rerr;
523b37e3 22840+ struct inode *delegated;
dece6358 22841+
b4510431
AM
22842+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
22843+ a->dst_h_parent);
4a4d8108
AM
22844+ rerr = PTR_ERR(a->h_path.dentry);
22845+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22846+ RevertFailure("lkup one %pd", a->dst_dentry);
4a4d8108
AM
22847+ return;
22848+ }
5527c038 22849+ if (d_is_positive(a->h_path.dentry)) {
4a4d8108
AM
22850+ d_drop(a->h_path.dentry);
22851+ dput(a->h_path.dentry);
22852+ return;
dece6358
AM
22853+ }
22854+
523b37e3
AM
22855+ delegated = NULL;
22856+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path,
f2c43d5f 22857+ &delegated, a->flags);
523b37e3
AM
22858+ if (unlikely(rerr == -EWOULDBLOCK)) {
22859+ pr_warn("cannot retry for NFSv4 delegation"
22860+ " for an internal rename\n");
22861+ iput(delegated);
22862+ }
4a4d8108
AM
22863+ d_drop(a->h_path.dentry);
22864+ dput(a->h_path.dentry);
22865+ if (!rerr)
22866+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
22867+ else
523b37e3 22868+ RevertFailure("rename %pd", a->h_dst);
4a4d8108 22869+}
1308ab2a 22870+
4a4d8108
AM
22871+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
22872+{
22873+ int rerr;
1308ab2a 22874+
4a4d8108
AM
22875+ a->h_path.dentry = a->src_wh_dentry;
22876+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 22877+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108 22878+ if (rerr)
523b37e3 22879+ RevertFailure("unlink %pd", a->src_wh_dentry);
4a4d8108 22880+}
4a4d8108 22881+#undef RevertFailure
1facf9fc 22882+
1308ab2a 22883+/* ---------------------------------------------------------------------- */
22884+
4a4d8108
AM
22885+/*
22886+ * when we have to copyup the renaming entry, do it with the rename-target name
22887+ * in order to minimize the cost (the later actual rename is unnecessary).
22888+ * otherwise rename it on the target branch.
22889+ */
22890+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 22891+{
dece6358 22892+ int err;
4a4d8108 22893+ struct dentry *d;
523b37e3 22894+ struct inode *delegated;
1facf9fc 22895+
4a4d8108 22896+ d = a->src_dentry;
5afbbe0d 22897+ if (au_dbtop(d) == a->btgt) {
4a4d8108 22898+ a->h_path.dentry = a->dst_h_dentry;
5afbbe0d 22899+ AuDebugOn(au_dbtop(d) != a->btgt);
523b37e3 22900+ delegated = NULL;
4a4d8108 22901+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
f2c43d5f
AM
22902+ a->dst_h_dir, &a->h_path, &delegated,
22903+ a->flags);
523b37e3
AM
22904+ if (unlikely(err == -EWOULDBLOCK)) {
22905+ pr_warn("cannot retry for NFSv4 delegation"
22906+ " for an internal rename\n");
22907+ iput(delegated);
22908+ }
c2b27bf2 22909+ } else
86dc4139 22910+ BUG();
1308ab2a 22911+
027c5e7a
AM
22912+ if (!err && a->h_dst)
22913+ /* it will be set to dinfo later */
22914+ dget(a->h_dst);
1facf9fc 22915+
dece6358
AM
22916+ return err;
22917+}
1facf9fc 22918+
4a4d8108
AM
22919+/* cf. aufs_rmdir() */
22920+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 22921+{
4a4d8108
AM
22922+ int err;
22923+ struct inode *dir;
1facf9fc 22924+
4a4d8108
AM
22925+ dir = a->dst_dir;
22926+ SiMustAnyLock(dir->i_sb);
22927+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
22928+ au_sbi(dir->i_sb)->si_dirwh)
22929+ || au_test_fs_remote(a->h_dst->d_sb)) {
22930+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
22931+ if (unlikely(err))
523b37e3
AM
22932+ pr_warn("failed removing whtmp dir %pd (%d), "
22933+ "ignored.\n", a->h_dst, err);
4a4d8108
AM
22934+ } else {
22935+ au_nhash_wh_free(&a->thargs->whlist);
22936+ a->thargs->whlist = a->whlist;
22937+ a->whlist.nh_num = 0;
22938+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
22939+ dput(a->h_dst);
22940+ a->thargs = NULL;
22941+ }
22942+
22943+ return 0;
1308ab2a 22944+}
1facf9fc 22945+
4a4d8108 22946+/* make it 'opaque' dir. */
f2c43d5f 22947+static int au_ren_do_diropq(struct au_ren_args *a, int idx)
4a4d8108
AM
22948+{
22949+ int err;
f2c43d5f
AM
22950+ struct dentry *d, *diropq;
22951+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22952+
4a4d8108 22953+ err = 0;
f2c43d5f
AM
22954+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22955+ src_or_dst(bdiropq) = au_dbdiropq(d);
22956+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt);
22957+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22958+ diropq = au_diropq_create(d, a->btgt);
22959+ au_hn_inode_unlock(src_or_dst(hinode));
4a4d8108
AM
22960+ if (IS_ERR(diropq))
22961+ err = PTR_ERR(diropq);
076b876e
AM
22962+ else
22963+ dput(diropq);
1facf9fc 22964+
f2c43d5f 22965+#undef src_or_dst_
4a4d8108
AM
22966+ return err;
22967+}
1facf9fc 22968+
f2c43d5f 22969+static int au_ren_diropq(struct au_ren_args *a)
4a4d8108
AM
22970+{
22971+ int err;
f2c43d5f
AM
22972+ unsigned char always;
22973+ struct dentry *d;
1facf9fc 22974+
f2c43d5f
AM
22975+ err = 0;
22976+ d = a->dst_dentry; /* already renamed on the branch */
22977+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ);
22978+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
8b6a4947 22979+ && !au_ftest_ren(a->auren_flags, DIRREN)
f2c43d5f
AM
22980+ && a->btgt != au_dbdiropq(a->src_dentry)
22981+ && (a->dst_wh_dentry
22982+ || a->btgt <= au_dbdiropq(d)
22983+ /* hide the lower to keep xino */
22984+ /* the lowers may not be a dir, but we hide them anyway */
22985+ || a->btgt < au_dbbot(d)
22986+ || always)) {
22987+ AuDbg("here\n");
22988+ err = au_ren_do_diropq(a, AuSRC);
22989+ if (unlikely(err))
4a4d8108 22990+ goto out;
f2c43d5f 22991+ au_fset_ren(a->auren_flags, DIROPQ_SRC);
4a4d8108 22992+ }
f2c43d5f
AM
22993+ if (!a->exchange)
22994+ goto out; /* success */
1facf9fc 22995+
f2c43d5f
AM
22996+ d = a->src_dentry; /* already renamed on the branch */
22997+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
22998+ && a->btgt != au_dbdiropq(a->dst_dentry)
22999+ && (a->btgt < au_dbdiropq(d)
23000+ || a->btgt < au_dbbot(d)
23001+ || always)) {
23002+ AuDbgDentry(a->src_dentry);
23003+ AuDbgDentry(a->dst_dentry);
23004+ err = au_ren_do_diropq(a, AuDST);
4a4d8108 23005+ if (unlikely(err))
f2c43d5f
AM
23006+ goto out_rev_src;
23007+ au_fset_ren(a->auren_flags, DIROPQ_DST);
23008+ }
23009+ goto out; /* success */
dece6358 23010+
f2c43d5f
AM
23011+out_rev_src:
23012+ AuDbg("err %d, reverting src\n", err);
23013+ au_ren_rev_diropq(err, a);
23014+out:
23015+ return err;
23016+}
23017+
23018+static int do_rename(struct au_ren_args *a)
23019+{
23020+ int err;
23021+ struct dentry *d, *h_d;
23022+
23023+ if (!a->exchange) {
23024+ /* prepare workqueue args for asynchronous rmdir */
23025+ h_d = a->dst_h_dentry;
23026+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
8b6a4947 23027+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */
f2c43d5f
AM
23028+ && d_is_positive(h_d)) {
23029+ err = -ENOMEM;
23030+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb,
23031+ GFP_NOFS);
23032+ if (unlikely(!a->thargs))
23033+ goto out;
23034+ a->h_dst = dget(h_d);
23035+ }
23036+
23037+ /* create whiteout for src_dentry */
23038+ if (au_ftest_ren(a->auren_flags, WHSRC)) {
23039+ a->src_bwh = au_dbwh(a->src_dentry);
23040+ AuDebugOn(a->src_bwh >= 0);
23041+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt,
23042+ a->src_h_parent);
23043+ err = PTR_ERR(a->src_wh_dentry);
23044+ if (IS_ERR(a->src_wh_dentry))
23045+ goto out_thargs;
23046+ }
23047+
23048+ /* lookup whiteout for dentry */
23049+ if (au_ftest_ren(a->auren_flags, WHDST)) {
23050+ h_d = au_wh_lkup(a->dst_h_parent,
23051+ &a->dst_dentry->d_name, a->br);
23052+ err = PTR_ERR(h_d);
23053+ if (IS_ERR(h_d))
23054+ goto out_whsrc;
23055+ if (d_is_negative(h_d))
23056+ dput(h_d);
23057+ else
23058+ a->dst_wh_dentry = h_d;
23059+ }
23060+
23061+ /* rename dentry to tmpwh */
23062+ if (a->thargs) {
23063+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
23064+ if (unlikely(err))
23065+ goto out_whdst;
23066+
23067+ d = a->dst_dentry;
23068+ au_set_h_dptr(d, a->btgt, NULL);
23069+ err = au_lkup_neg(d, a->btgt, /*wh*/0);
23070+ if (unlikely(err))
23071+ goto out_whtmp;
23072+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
23073+ }
4a4d8108 23074+ }
1facf9fc 23075+
5afbbe0d 23076+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt);
8b6a4947
AM
23077+#if 0
23078+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN)
23079+ && d_is_positive(a->dst_h_dentry)
23080+ && a->src_btop != a->btgt);
23081+#endif
1facf9fc 23082+
4a4d8108 23083+ /* rename by vfs_rename or cpup */
4a4d8108
AM
23084+ err = au_ren_or_cpup(a);
23085+ if (unlikely(err))
23086+ /* leave the copied-up one */
23087+ goto out_whtmp;
1308ab2a 23088+
4a4d8108 23089+ /* make dir opaque */
f2c43d5f
AM
23090+ err = au_ren_diropq(a);
23091+ if (unlikely(err))
23092+ goto out_rename;
1308ab2a 23093+
4a4d8108 23094+ /* update target timestamps */
f2c43d5f
AM
23095+ if (a->exchange) {
23096+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt);
23097+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt);
23098+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
23099+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
23100+ }
5afbbe0d 23101+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt);
4a4d8108
AM
23102+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
23103+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
5527c038 23104+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
1facf9fc 23105+
f2c43d5f
AM
23106+ if (!a->exchange) {
23107+ /* remove whiteout for dentry */
23108+ if (a->dst_wh_dentry) {
23109+ a->h_path.dentry = a->dst_wh_dentry;
23110+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
23111+ a->dst_dentry);
23112+ if (unlikely(err))
23113+ goto out_diropq;
23114+ }
1facf9fc 23115+
f2c43d5f
AM
23116+ /* remove whtmp */
23117+ if (a->thargs)
23118+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 23119+
f2c43d5f
AM
23120+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0);
23121+ }
4a4d8108
AM
23122+ err = 0;
23123+ goto out_success;
23124+
4f0767ce 23125+out_diropq:
f2c43d5f 23126+ au_ren_rev_diropq(err, a);
4f0767ce 23127+out_rename:
7e9cd9fe 23128+ au_ren_rev_rename(err, a);
027c5e7a 23129+ dput(a->h_dst);
4f0767ce 23130+out_whtmp:
4a4d8108
AM
23131+ if (a->thargs)
23132+ au_ren_rev_whtmp(err, a);
4f0767ce 23133+out_whdst:
4a4d8108
AM
23134+ dput(a->dst_wh_dentry);
23135+ a->dst_wh_dentry = NULL;
4f0767ce 23136+out_whsrc:
4a4d8108
AM
23137+ if (a->src_wh_dentry)
23138+ au_ren_rev_whsrc(err, a);
4f0767ce 23139+out_success:
4a4d8108
AM
23140+ dput(a->src_wh_dentry);
23141+ dput(a->dst_wh_dentry);
4f0767ce 23142+out_thargs:
4a4d8108
AM
23143+ if (a->thargs) {
23144+ dput(a->h_dst);
23145+ au_whtmp_rmdir_free(a->thargs);
23146+ a->thargs = NULL;
23147+ }
4f0767ce 23148+out:
4a4d8108 23149+ return err;
dece6358 23150+}
1facf9fc 23151+
1308ab2a 23152+/* ---------------------------------------------------------------------- */
1facf9fc 23153+
4a4d8108
AM
23154+/*
23155+ * test if @dentry dir can be rename destination or not.
23156+ * success means, it is a logically empty dir.
23157+ */
23158+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 23159+{
4a4d8108 23160+ return au_test_empty(dentry, whlist);
1308ab2a 23161+}
1facf9fc 23162+
4a4d8108 23163+/*
8b6a4947
AM
23164+ * test if @a->src_dentry dir can be rename source or not.
23165+ * if it can, return 0.
4a4d8108
AM
23166+ * success means,
23167+ * - it is a logically empty dir.
23168+ * - or, it exists on writable branch and has no children including whiteouts
8b6a4947 23169+ * on the lower branch unless DIRREN is on.
4a4d8108 23170+ */
8b6a4947 23171+static int may_rename_srcdir(struct au_ren_args *a)
4a4d8108
AM
23172+{
23173+ int err;
23174+ unsigned int rdhash;
8b6a4947
AM
23175+ aufs_bindex_t btop, btgt;
23176+ struct dentry *dentry;
23177+ struct super_block *sb;
23178+ struct au_sbinfo *sbinfo;
1facf9fc 23179+
8b6a4947
AM
23180+ dentry = a->src_dentry;
23181+ sb = dentry->d_sb;
23182+ sbinfo = au_sbi(sb);
23183+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
23184+ au_fset_ren(a->auren_flags, DIRREN);
23185+
23186+ btgt = a->btgt;
5afbbe0d
AM
23187+ btop = au_dbtop(dentry);
23188+ if (btop != btgt) {
4a4d8108 23189+ struct au_nhash whlist;
dece6358 23190+
8b6a4947
AM
23191+ SiMustAnyLock(sb);
23192+ rdhash = sbinfo->si_rdhash;
4a4d8108
AM
23193+ if (!rdhash)
23194+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
23195+ dentry));
23196+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
23197+ if (unlikely(err))
23198+ goto out;
23199+ err = au_test_empty(dentry, &whlist);
23200+ au_nhash_wh_free(&whlist);
23201+ goto out;
23202+ }
dece6358 23203+
5afbbe0d 23204+ if (btop == au_dbtaildir(dentry))
4a4d8108 23205+ return 0; /* success */
dece6358 23206+
4a4d8108 23207+ err = au_test_empty_lower(dentry);
1facf9fc 23208+
4f0767ce 23209+out:
4a4d8108 23210+ if (err == -ENOTEMPTY) {
8b6a4947
AM
23211+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23212+ err = 0;
23213+ } else {
23214+ AuWarn1("renaming dir who has child(ren) on multiple "
23215+ "branches, is not supported\n");
23216+ err = -EXDEV;
23217+ }
4a4d8108
AM
23218+ }
23219+ return err;
23220+}
1308ab2a 23221+
4a4d8108
AM
23222+/* side effect: sets whlist and h_dentry */
23223+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 23224+{
4a4d8108
AM
23225+ int err;
23226+ unsigned int rdhash;
23227+ struct dentry *d;
1facf9fc 23228+
4a4d8108
AM
23229+ d = a->dst_dentry;
23230+ SiMustAnyLock(d->d_sb);
1facf9fc 23231+
4a4d8108 23232+ err = 0;
f2c43d5f 23233+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) {
4a4d8108
AM
23234+ rdhash = au_sbi(d->d_sb)->si_rdhash;
23235+ if (!rdhash)
23236+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
23237+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
23238+ if (unlikely(err))
23239+ goto out;
1308ab2a 23240+
f2c43d5f
AM
23241+ if (!a->exchange) {
23242+ au_set_dbtop(d, a->dst_btop);
23243+ err = may_rename_dstdir(d, &a->whlist);
23244+ au_set_dbtop(d, a->btgt);
23245+ } else
8b6a4947 23246+ err = may_rename_srcdir(a);
4a4d8108 23247+ }
5afbbe0d 23248+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d));
4a4d8108
AM
23249+ if (unlikely(err))
23250+ goto out;
23251+
23252+ d = a->src_dentry;
5afbbe0d 23253+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d));
f2c43d5f 23254+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
8b6a4947 23255+ err = may_rename_srcdir(a);
4a4d8108
AM
23256+ if (unlikely(err)) {
23257+ au_nhash_wh_free(&a->whlist);
23258+ a->whlist.nh_num = 0;
23259+ }
23260+ }
4f0767ce 23261+out:
4a4d8108 23262+ return err;
1facf9fc 23263+}
23264+
4a4d8108 23265+/* ---------------------------------------------------------------------- */
1facf9fc 23266+
4a4d8108
AM
23267+/*
23268+ * simple tests for rename.
23269+ * following the checks in vfs, plus the parent-child relationship.
23270+ */
23271+static int au_may_ren(struct au_ren_args *a)
23272+{
23273+ int err, isdir;
23274+ struct inode *h_inode;
1facf9fc 23275+
5afbbe0d 23276+ if (a->src_btop == a->btgt) {
4a4d8108 23277+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
f2c43d5f 23278+ au_ftest_ren(a->auren_flags, ISDIR_SRC));
4a4d8108
AM
23279+ if (unlikely(err))
23280+ goto out;
23281+ err = -EINVAL;
23282+ if (unlikely(a->src_h_dentry == a->h_trap))
23283+ goto out;
23284+ }
1facf9fc 23285+
4a4d8108 23286+ err = 0;
5afbbe0d 23287+ if (a->dst_btop != a->btgt)
4a4d8108 23288+ goto out;
1facf9fc 23289+
027c5e7a
AM
23290+ err = -ENOTEMPTY;
23291+ if (unlikely(a->dst_h_dentry == a->h_trap))
23292+ goto out;
23293+
4a4d8108 23294+ err = -EIO;
f2c43d5f 23295+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST);
5527c038
JR
23296+ if (d_really_is_negative(a->dst_dentry)) {
23297+ if (d_is_negative(a->dst_h_dentry))
23298+ err = au_may_add(a->dst_dentry, a->btgt,
23299+ a->dst_h_parent, isdir);
4a4d8108 23300+ } else {
5527c038 23301+ if (unlikely(d_is_negative(a->dst_h_dentry)))
4a4d8108 23302+ goto out;
5527c038
JR
23303+ h_inode = d_inode(a->dst_h_dentry);
23304+ if (h_inode->i_nlink)
23305+ err = au_may_del(a->dst_dentry, a->btgt,
23306+ a->dst_h_parent, isdir);
4a4d8108 23307+ }
1facf9fc 23308+
4f0767ce 23309+out:
4a4d8108
AM
23310+ if (unlikely(err == -ENOENT || err == -EEXIST))
23311+ err = -EIO;
23312+ AuTraceErr(err);
23313+ return err;
23314+}
1facf9fc 23315+
1308ab2a 23316+/* ---------------------------------------------------------------------- */
1facf9fc 23317+
4a4d8108
AM
23318+/*
23319+ * locking order
23320+ * (VFS)
23321+ * - src_dir and dir by lock_rename()
acd2b654 23322+ * - inode if exists
4a4d8108
AM
23323+ * (aufs)
23324+ * - lock all
23325+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
23326+ * + si_read_lock
23327+ * + di_write_lock2_child()
23328+ * + di_write_lock_child()
23329+ * + ii_write_lock_child()
23330+ * + di_write_lock_child2()
23331+ * + ii_write_lock_child2()
23332+ * + src_parent and parent
23333+ * + di_write_lock_parent()
23334+ * + ii_write_lock_parent()
23335+ * + di_write_lock_parent2()
23336+ * + ii_write_lock_parent2()
23337+ * + lower src_dir and dir by vfsub_lock_rename()
23338+ * + verify the every relationships between child and parent. if any
23339+ * of them failed, unlock all and return -EBUSY.
23340+ */
23341+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 23342+{
4a4d8108
AM
23343+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
23344+ a->dst_h_parent, a->dst_hdir);
8b6a4947
AM
23345+ if (au_ftest_ren(a->auren_flags, DIRREN)
23346+ && a->h_root)
23347+ au_hn_inode_unlock(a->h_root);
f2c43d5f 23348+ if (au_ftest_ren(a->auren_flags, MNT_WRITE))
86dc4139 23349+ vfsub_mnt_drop_write(au_br_mnt(a->br));
1308ab2a 23350+}
23351+
4a4d8108 23352+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 23353+{
4a4d8108
AM
23354+ int err;
23355+ unsigned int udba;
1308ab2a 23356+
4a4d8108
AM
23357+ err = 0;
23358+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
23359+ a->src_hdir = au_hi(a->src_dir, a->btgt);
23360+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
23361+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
86dc4139
AM
23362+
23363+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
23364+ if (unlikely(err))
23365+ goto out;
f2c43d5f 23366+ au_fset_ren(a->auren_flags, MNT_WRITE);
8b6a4947
AM
23367+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23368+ struct dentry *root;
23369+ struct inode *dir;
23370+
23371+ /*
23372+ * sbinfo is already locked, so this ii_read_lock is
23373+ * unnecessary. but our debugging feature checks it.
23374+ */
23375+ root = a->src_inode->i_sb->s_root;
23376+ if (root != a->src_parent && root != a->dst_parent) {
23377+ dir = d_inode(root);
23378+ ii_read_lock_parent3(dir);
23379+ a->h_root = au_hi(dir, a->btgt);
23380+ ii_read_unlock(dir);
23381+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3);
23382+ }
23383+ }
4a4d8108
AM
23384+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
23385+ a->dst_h_parent, a->dst_hdir);
23386+ udba = au_opt_udba(a->src_dentry->d_sb);
5527c038
JR
23387+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent)
23388+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent)))
4a4d8108 23389+ err = au_busy_or_stale();
5afbbe0d 23390+ if (!err && au_dbtop(a->src_dentry) == a->btgt)
4a4d8108 23391+ err = au_h_verify(a->src_h_dentry, udba,
5527c038 23392+ d_inode(a->src_h_parent), a->src_h_parent,
4a4d8108 23393+ a->br);
5afbbe0d 23394+ if (!err && au_dbtop(a->dst_dentry) == a->btgt)
4a4d8108 23395+ err = au_h_verify(a->dst_h_dentry, udba,
5527c038 23396+ d_inode(a->dst_h_parent), a->dst_h_parent,
4a4d8108 23397+ a->br);
86dc4139 23398+ if (!err)
4a4d8108 23399+ goto out; /* success */
4a4d8108
AM
23400+
23401+ err = au_busy_or_stale();
4a4d8108 23402+ au_ren_unlock(a);
86dc4139 23403+
4f0767ce 23404+out:
4a4d8108 23405+ return err;
1facf9fc 23406+}
23407+
23408+/* ---------------------------------------------------------------------- */
23409+
4a4d8108 23410+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 23411+{
4a4d8108 23412+ struct inode *dir;
dece6358 23413+
4a4d8108 23414+ dir = a->dst_dir;
be118d29 23415+ inode_inc_iversion(dir);
f2c43d5f 23416+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
4a4d8108
AM
23417+ /* is this updating defined in POSIX? */
23418+ au_cpup_attr_timesizes(a->src_inode);
23419+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 23420+ }
b912730e 23421+ au_dir_ts(dir, a->btgt);
dece6358 23422+
f2c43d5f
AM
23423+ if (a->exchange) {
23424+ dir = a->src_dir;
be118d29 23425+ inode_inc_iversion(dir);
f2c43d5f
AM
23426+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) {
23427+ /* is this updating defined in POSIX? */
23428+ au_cpup_attr_timesizes(a->dst_inode);
23429+ au_cpup_attr_nlink(dir, /*force*/1);
23430+ }
23431+ au_dir_ts(dir, a->btgt);
23432+ }
23433+
23434+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108 23435+ return;
dece6358 23436+
4a4d8108 23437+ dir = a->src_dir;
be118d29 23438+ inode_inc_iversion(dir);
f2c43d5f 23439+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC))
4a4d8108 23440+ au_cpup_attr_nlink(dir, /*force*/1);
b912730e 23441+ au_dir_ts(dir, a->btgt);
1facf9fc 23442+}
23443+
4a4d8108 23444+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 23445+{
5afbbe0d 23446+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
23447+ struct dentry *d, *h_d;
23448+ struct inode *i, *h_i;
23449+ struct super_block *sb;
dece6358 23450+
027c5e7a
AM
23451+ d = a->dst_dentry;
23452+ d_drop(d);
23453+ if (a->h_dst)
23454+ /* already dget-ed by au_ren_or_cpup() */
23455+ au_set_h_dptr(d, a->btgt, a->h_dst);
23456+
23457+ i = a->dst_inode;
23458+ if (i) {
f2c43d5f
AM
23459+ if (!a->exchange) {
23460+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST))
23461+ vfsub_drop_nlink(i);
23462+ else {
23463+ vfsub_dead_dir(i);
23464+ au_cpup_attr_timesizes(i);
23465+ }
23466+ au_update_dbrange(d, /*do_put_zero*/1);
23467+ } else
23468+ au_cpup_attr_nlink(i, /*force*/1);
027c5e7a 23469+ } else {
5afbbe0d
AM
23470+ bbot = a->btgt;
23471+ for (bindex = au_dbtop(d); bindex < bbot; bindex++)
027c5e7a 23472+ au_set_h_dptr(d, bindex, NULL);
5afbbe0d
AM
23473+ bbot = au_dbbot(d);
23474+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++)
027c5e7a
AM
23475+ au_set_h_dptr(d, bindex, NULL);
23476+ au_update_dbrange(d, /*do_put_zero*/0);
23477+ }
23478+
8b6a4947
AM
23479+ if (a->exchange
23480+ || au_ftest_ren(a->auren_flags, DIRREN)) {
23481+ d_drop(a->src_dentry);
23482+ if (au_ftest_ren(a->auren_flags, DIRREN))
23483+ au_set_dbwh(a->src_dentry, -1);
23484+ return;
23485+ }
23486+
4a4d8108 23487+ d = a->src_dentry;
8b6a4947
AM
23488+ au_set_dbwh(d, -1);
23489+ bbot = au_dbbot(d);
23490+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23491+ h_d = au_h_dptr(d, bindex);
23492+ if (h_d)
23493+ au_set_h_dptr(d, bindex, NULL);
23494+ }
23495+ au_set_dbbot(d, a->btgt);
4a4d8108 23496+
8b6a4947
AM
23497+ sb = d->d_sb;
23498+ i = a->src_inode;
23499+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
23500+ return; /* success */
4a4d8108 23501+
8b6a4947
AM
23502+ bbot = au_ibbot(i);
23503+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23504+ h_i = au_h_iptr(i, bindex);
23505+ if (h_i) {
23506+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
23507+ /* ignore this error */
23508+ au_set_h_iptr(i, bindex, NULL, 0);
4a4d8108
AM
23509+ }
23510+ }
8b6a4947 23511+ au_set_ibbot(i, a->btgt);
1308ab2a 23512+}
dece6358 23513+
4a4d8108
AM
23514+/* ---------------------------------------------------------------------- */
23515+
23516+/* mainly for link(2) and rename(2) */
23517+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 23518+{
4a4d8108
AM
23519+ aufs_bindex_t bdiropq, bwh;
23520+ struct dentry *parent;
23521+ struct au_branch *br;
23522+
23523+ parent = dentry->d_parent;
5527c038 23524+ IMustLock(d_inode(parent)); /* dir is locked */
4a4d8108
AM
23525+
23526+ bdiropq = au_dbdiropq(parent);
23527+ bwh = au_dbwh(dentry);
23528+ br = au_sbr(dentry->d_sb, btgt);
23529+ if (au_br_rdonly(br)
23530+ || (0 <= bdiropq && bdiropq < btgt)
23531+ || (0 <= bwh && bwh < btgt))
23532+ btgt = -1;
23533+
23534+ AuDbg("btgt %d\n", btgt);
23535+ return btgt;
1facf9fc 23536+}
23537+
5afbbe0d 23538+/* sets src_btop, dst_btop and btgt */
4a4d8108 23539+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 23540+{
4a4d8108
AM
23541+ int err;
23542+ struct au_wr_dir_args wr_dir_args = {
23543+ /* .force_btgt = -1, */
23544+ .flags = AuWrDir_ADD_ENTRY
23545+ };
dece6358 23546+
5afbbe0d
AM
23547+ a->src_btop = au_dbtop(a->src_dentry);
23548+ a->dst_btop = au_dbtop(a->dst_dentry);
f2c43d5f
AM
23549+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
23550+ || au_ftest_ren(a->auren_flags, ISDIR_DST))
4a4d8108 23551+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
5afbbe0d
AM
23552+ wr_dir_args.force_btgt = a->src_btop;
23553+ if (a->dst_inode && a->dst_btop < a->src_btop)
23554+ wr_dir_args.force_btgt = a->dst_btop;
4a4d8108
AM
23555+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
23556+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
23557+ a->btgt = err;
f2c43d5f
AM
23558+ if (a->exchange)
23559+ au_update_dbtop(a->dst_dentry);
dece6358 23560+
4a4d8108 23561+ return err;
1facf9fc 23562+}
23563+
4a4d8108 23564+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 23565+{
4a4d8108
AM
23566+ a->h_path.dentry = a->src_h_parent;
23567+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
f2c43d5f 23568+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) {
4a4d8108
AM
23569+ a->h_path.dentry = a->dst_h_parent;
23570+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
23571+ }
1facf9fc 23572+
f2c43d5f
AM
23573+ au_fclr_ren(a->auren_flags, DT_DSTDIR);
23574+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC)
23575+ && !a->exchange)
4a4d8108 23576+ return;
dece6358 23577+
4a4d8108
AM
23578+ a->h_path.dentry = a->src_h_dentry;
23579+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
5527c038 23580+ if (d_is_positive(a->dst_h_dentry)) {
f2c43d5f 23581+ au_fset_ren(a->auren_flags, DT_DSTDIR);
4a4d8108
AM
23582+ a->h_path.dentry = a->dst_h_dentry;
23583+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
23584+ }
1308ab2a 23585+}
dece6358 23586+
4a4d8108 23587+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 23588+{
4a4d8108 23589+ struct dentry *h_d;
febd17d6 23590+ struct inode *h_inode;
4a4d8108
AM
23591+
23592+ au_dtime_revert(a->src_dt + AuPARENT);
f2c43d5f 23593+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23594+ au_dtime_revert(a->dst_dt + AuPARENT);
23595+
f2c43d5f 23596+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) {
4a4d8108 23597+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23598+ h_inode = d_inode(h_d);
23599+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23600+ au_dtime_revert(a->src_dt + AuCHILD);
febd17d6 23601+ inode_unlock(h_inode);
4a4d8108 23602+
f2c43d5f 23603+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) {
4a4d8108 23604+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23605+ h_inode = d_inode(h_d);
23606+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23607+ au_dtime_revert(a->dst_dt + AuCHILD);
febd17d6 23608+ inode_unlock(h_inode);
1facf9fc 23609+ }
23610+ }
23611+}
23612+
4a4d8108
AM
23613+/* ---------------------------------------------------------------------- */
23614+
23615+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
f2c43d5f
AM
23616+ struct inode *_dst_dir, struct dentry *_dst_dentry,
23617+ unsigned int _flags)
1facf9fc 23618+{
f2c43d5f 23619+ int err, lock_flags;
8b6a4947 23620+ void *rev;
4a4d8108
AM
23621+ /* reduce stack space */
23622+ struct au_ren_args *a;
f2c43d5f 23623+ struct au_pin pin;
4a4d8108 23624+
f2c43d5f 23625+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags);
4a4d8108
AM
23626+ IMustLock(_src_dir);
23627+ IMustLock(_dst_dir);
23628+
f2c43d5f
AM
23629+ err = -EINVAL;
23630+ if (unlikely(_flags & RENAME_WHITEOUT))
23631+ goto out;
23632+
4a4d8108
AM
23633+ err = -ENOMEM;
23634+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
23635+ a = kzalloc(sizeof(*a), GFP_NOFS);
23636+ if (unlikely(!a))
23637+ goto out;
23638+
f2c43d5f 23639+ a->flags = _flags;
acd2b654
AM
23640+ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8)
23641+ && RENAME_EXCHANGE > U8_MAX);
f2c43d5f 23642+ a->exchange = _flags & RENAME_EXCHANGE;
4a4d8108
AM
23643+ a->src_dir = _src_dir;
23644+ a->src_dentry = _src_dentry;
5527c038
JR
23645+ a->src_inode = NULL;
23646+ if (d_really_is_positive(a->src_dentry))
23647+ a->src_inode = d_inode(a->src_dentry);
4a4d8108
AM
23648+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
23649+ a->dst_dir = _dst_dir;
23650+ a->dst_dentry = _dst_dentry;
5527c038
JR
23651+ a->dst_inode = NULL;
23652+ if (d_really_is_positive(a->dst_dentry))
23653+ a->dst_inode = d_inode(a->dst_dentry);
4a4d8108
AM
23654+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
23655+ if (a->dst_inode) {
f2c43d5f
AM
23656+ /*
23657+ * if EXCHANGE && src is non-dir && dst is dir,
23658+ * dst is not locked.
23659+ */
23660+ /* IMustLock(a->dst_inode); */
4a4d8108 23661+ au_igrab(a->dst_inode);
1facf9fc 23662+ }
1facf9fc 23663+
4a4d8108 23664+ err = -ENOTDIR;
f2c43d5f 23665+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
2000de60 23666+ if (d_is_dir(a->src_dentry)) {
f2c43d5f
AM
23667+ au_fset_ren(a->auren_flags, ISDIR_SRC);
23668+ if (unlikely(!a->exchange
23669+ && d_really_is_positive(a->dst_dentry)
2000de60 23670+ && !d_is_dir(a->dst_dentry)))
4a4d8108 23671+ goto out_free;
f2c43d5f
AM
23672+ lock_flags |= AuLock_DIRS;
23673+ }
23674+ if (a->dst_inode && d_is_dir(a->dst_dentry)) {
23675+ au_fset_ren(a->auren_flags, ISDIR_DST);
23676+ if (unlikely(!a->exchange
23677+ && d_really_is_positive(a->src_dentry)
23678+ && !d_is_dir(a->src_dentry)))
23679+ goto out_free;
23680+ lock_flags |= AuLock_DIRS;
b95c5147 23681+ }
8b6a4947
AM
23682+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
23683+ lock_flags);
e49829fe
JR
23684+ if (unlikely(err))
23685+ goto out_free;
1facf9fc 23686+
027c5e7a
AM
23687+ err = au_d_hashed_positive(a->src_dentry);
23688+ if (unlikely(err))
23689+ goto out_unlock;
23690+ err = -ENOENT;
23691+ if (a->dst_inode) {
23692+ /*
f2c43d5f 23693+ * If it is a dir, VFS unhash it before this
027c5e7a
AM
23694+ * function. It means we cannot rely upon d_unhashed().
23695+ */
23696+ if (unlikely(!a->dst_inode->i_nlink))
23697+ goto out_unlock;
f2c43d5f 23698+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) {
027c5e7a 23699+ err = au_d_hashed_positive(a->dst_dentry);
f2c43d5f 23700+ if (unlikely(err && !a->exchange))
027c5e7a
AM
23701+ goto out_unlock;
23702+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
23703+ goto out_unlock;
23704+ } else if (unlikely(d_unhashed(a->dst_dentry)))
23705+ goto out_unlock;
23706+
7eafdf33
AM
23707+ /*
23708+ * is it possible?
79b8bda9 23709+ * yes, it happened (in linux-3.3-rcN) but I don't know why.
7eafdf33
AM
23710+ * there may exist a problem somewhere else.
23711+ */
23712+ err = -EINVAL;
5527c038 23713+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry)))
7eafdf33
AM
23714+ goto out_unlock;
23715+
f2c43d5f 23716+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */
4a4d8108 23717+ di_write_lock_parent(a->dst_parent);
1facf9fc 23718+
4a4d8108
AM
23719+ /* which branch we process */
23720+ err = au_ren_wbr(a);
23721+ if (unlikely(err < 0))
027c5e7a 23722+ goto out_parent;
4a4d8108 23723+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
86dc4139 23724+ a->h_path.mnt = au_br_mnt(a->br);
1facf9fc 23725+
4a4d8108
AM
23726+ /* are they available to be renamed */
23727+ err = au_ren_may_dir(a);
23728+ if (unlikely(err))
23729+ goto out_children;
1facf9fc 23730+
4a4d8108 23731+ /* prepare the writable parent dir on the same branch */
5afbbe0d 23732+ if (a->dst_btop == a->btgt) {
f2c43d5f 23733+ au_fset_ren(a->auren_flags, WHDST);
4a4d8108
AM
23734+ } else {
23735+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
23736+ if (unlikely(err))
23737+ goto out_children;
23738+ }
1facf9fc 23739+
f2c43d5f
AM
23740+ err = 0;
23741+ if (!a->exchange) {
23742+ if (a->src_dir != a->dst_dir) {
23743+ /*
23744+ * this temporary unlock is safe,
23745+ * because both dir->i_mutex are locked.
23746+ */
23747+ di_write_unlock(a->dst_parent);
23748+ di_write_lock_parent(a->src_parent);
23749+ err = au_wr_dir_need_wh(a->src_dentry,
23750+ au_ftest_ren(a->auren_flags,
23751+ ISDIR_SRC),
23752+ &a->btgt);
23753+ di_write_unlock(a->src_parent);
23754+ di_write_lock2_parent(a->src_parent, a->dst_parent,
23755+ /*isdir*/1);
23756+ au_fclr_ren(a->auren_flags, ISSAMEDIR);
23757+ } else
23758+ err = au_wr_dir_need_wh(a->src_dentry,
23759+ au_ftest_ren(a->auren_flags,
23760+ ISDIR_SRC),
23761+ &a->btgt);
23762+ }
4a4d8108
AM
23763+ if (unlikely(err < 0))
23764+ goto out_children;
23765+ if (err)
f2c43d5f 23766+ au_fset_ren(a->auren_flags, WHSRC);
1facf9fc 23767+
86dc4139 23768+ /* cpup src */
5afbbe0d 23769+ if (a->src_btop != a->btgt) {
86dc4139
AM
23770+ err = au_pin(&pin, a->src_dentry, a->btgt,
23771+ au_opt_udba(a->src_dentry->d_sb),
23772+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 23773+ if (!err) {
c2b27bf2
AM
23774+ struct au_cp_generic cpg = {
23775+ .dentry = a->src_dentry,
23776+ .bdst = a->btgt,
5afbbe0d 23777+ .bsrc = a->src_btop,
c2b27bf2
AM
23778+ .len = -1,
23779+ .pin = &pin,
23780+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23781+ };
5afbbe0d 23782+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop);
c2b27bf2 23783+ err = au_sio_cpup_simple(&cpg);
367653fa 23784+ au_unpin(&pin);
86dc4139 23785+ }
86dc4139
AM
23786+ if (unlikely(err))
23787+ goto out_children;
5afbbe0d 23788+ a->src_btop = a->btgt;
86dc4139 23789+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt);
f2c43d5f
AM
23790+ if (!a->exchange)
23791+ au_fset_ren(a->auren_flags, WHSRC);
23792+ }
23793+
23794+ /* cpup dst */
23795+ if (a->exchange && a->dst_inode
23796+ && a->dst_btop != a->btgt) {
23797+ err = au_pin(&pin, a->dst_dentry, a->btgt,
23798+ au_opt_udba(a->dst_dentry->d_sb),
23799+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
23800+ if (!err) {
23801+ struct au_cp_generic cpg = {
23802+ .dentry = a->dst_dentry,
23803+ .bdst = a->btgt,
23804+ .bsrc = a->dst_btop,
23805+ .len = -1,
23806+ .pin = &pin,
23807+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23808+ };
23809+ err = au_sio_cpup_simple(&cpg);
23810+ au_unpin(&pin);
23811+ }
23812+ if (unlikely(err))
23813+ goto out_children;
23814+ a->dst_btop = a->btgt;
23815+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt);
86dc4139
AM
23816+ }
23817+
4a4d8108
AM
23818+ /* lock them all */
23819+ err = au_ren_lock(a);
23820+ if (unlikely(err))
86dc4139 23821+ /* leave the copied-up one */
4a4d8108 23822+ goto out_children;
1facf9fc 23823+
f2c43d5f
AM
23824+ if (!a->exchange) {
23825+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
23826+ err = au_may_ren(a);
23827+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
23828+ err = -ENAMETOOLONG;
23829+ if (unlikely(err))
23830+ goto out_hdir;
23831+ }
1facf9fc 23832+
4a4d8108
AM
23833+ /* store timestamps to be revertible */
23834+ au_ren_dt(a);
1facf9fc 23835+
8b6a4947
AM
23836+ /* store dirren info */
23837+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23838+ err = au_dr_rename(a->src_dentry, a->btgt,
23839+ &a->dst_dentry->d_name, &rev);
23840+ AuTraceErr(err);
23841+ if (unlikely(err))
23842+ goto out_dt;
23843+ }
23844+
4a4d8108
AM
23845+ /* here we go */
23846+ err = do_rename(a);
23847+ if (unlikely(err))
8b6a4947
AM
23848+ goto out_dirren;
23849+
23850+ if (au_ftest_ren(a->auren_flags, DIRREN))
23851+ au_dr_rename_fin(a->src_dentry, a->btgt, rev);
4a4d8108
AM
23852+
23853+ /* update dir attributes */
23854+ au_ren_refresh_dir(a);
23855+
23856+ /* dput/iput all lower dentries */
23857+ au_ren_refresh(a);
23858+
23859+ goto out_hdir; /* success */
23860+
8b6a4947
AM
23861+out_dirren:
23862+ if (au_ftest_ren(a->auren_flags, DIRREN))
23863+ au_dr_rename_rev(a->src_dentry, a->btgt, rev);
4f0767ce 23864+out_dt:
4a4d8108 23865+ au_ren_rev_dt(err, a);
4f0767ce 23866+out_hdir:
4a4d8108 23867+ au_ren_unlock(a);
4f0767ce 23868+out_children:
4a4d8108 23869+ au_nhash_wh_free(&a->whlist);
5afbbe0d
AM
23870+ if (err && a->dst_inode && a->dst_btop != a->btgt) {
23871+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt);
027c5e7a 23872+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
5afbbe0d 23873+ au_set_dbtop(a->dst_dentry, a->dst_btop);
4a4d8108 23874+ }
027c5e7a 23875+out_parent:
f2c43d5f 23876+ if (!err) {
8b6a4947
AM
23877+ if (d_unhashed(a->src_dentry))
23878+ au_fset_ren(a->auren_flags, DROPPED_SRC);
23879+ if (d_unhashed(a->dst_dentry))
23880+ au_fset_ren(a->auren_flags, DROPPED_DST);
f2c43d5f
AM
23881+ if (!a->exchange)
23882+ d_move(a->src_dentry, a->dst_dentry);
8b6a4947 23883+ else {
f2c43d5f 23884+ d_exchange(a->src_dentry, a->dst_dentry);
8b6a4947
AM
23885+ if (au_ftest_ren(a->auren_flags, DROPPED_DST))
23886+ d_drop(a->dst_dentry);
23887+ }
23888+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC))
23889+ d_drop(a->src_dentry);
f2c43d5f 23890+ } else {
5afbbe0d 23891+ au_update_dbtop(a->dst_dentry);
027c5e7a
AM
23892+ if (!a->dst_inode)
23893+ d_drop(a->dst_dentry);
23894+ }
f2c43d5f 23895+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23896+ di_write_unlock(a->dst_parent);
23897+ else
23898+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 23899+out_unlock:
4a4d8108 23900+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 23901+out_free:
4a4d8108
AM
23902+ iput(a->dst_inode);
23903+ if (a->thargs)
23904+ au_whtmp_rmdir_free(a->thargs);
9f237c51 23905+ au_kfree_rcu(a);
4f0767ce 23906+out:
4a4d8108
AM
23907+ AuTraceErr(err);
23908+ return err;
1308ab2a 23909+}
7f207e10 23910diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
fbc438ed
JR
23911--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 08:00:00.000000000 +0800
23912+++ linux/fs/aufs/Kconfig 2019-07-11 21:21:54.379051070 +0800
2121bcd9
AM
23913@@ -0,0 +1,199 @@
23914+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
23915+config AUFS_FS
23916+ tristate "Aufs (Advanced multi layered unification filesystem) support"
4a4d8108
AM
23917+ help
23918+ Aufs is a stackable unification filesystem such as Unionfs,
23919+ which unifies several directories and provides a merged single
23920+ directory.
23921+ In the early days, aufs was entirely re-designed and
23922+ re-implemented Unionfs Version 1.x series. Introducing many
23923+ original ideas, approaches and improvements, it becomes totally
23924+ different from Unionfs while keeping the basic features.
1facf9fc 23925+
4a4d8108
AM
23926+if AUFS_FS
23927+choice
23928+ prompt "Maximum number of branches"
23929+ default AUFS_BRANCH_MAX_127
23930+ help
23931+ Specifies the maximum number of branches (or member directories)
23932+ in a single aufs. The larger value consumes more system
23933+ resources and has a minor impact to performance.
23934+config AUFS_BRANCH_MAX_127
23935+ bool "127"
23936+ help
23937+ Specifies the maximum number of branches (or member directories)
23938+ in a single aufs. The larger value consumes more system
23939+ resources and has a minor impact to performance.
23940+config AUFS_BRANCH_MAX_511
23941+ bool "511"
23942+ help
23943+ Specifies the maximum number of branches (or member directories)
23944+ in a single aufs. The larger value consumes more system
23945+ resources and has a minor impact to performance.
23946+config AUFS_BRANCH_MAX_1023
23947+ bool "1023"
23948+ help
23949+ Specifies the maximum number of branches (or member directories)
23950+ in a single aufs. The larger value consumes more system
23951+ resources and has a minor impact to performance.
23952+config AUFS_BRANCH_MAX_32767
23953+ bool "32767"
23954+ help
23955+ Specifies the maximum number of branches (or member directories)
23956+ in a single aufs. The larger value consumes more system
23957+ resources and has a minor impact to performance.
23958+endchoice
1facf9fc 23959+
e49829fe
JR
23960+config AUFS_SBILIST
23961+ bool
23962+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
23963+ default y
23964+ help
23965+ Automatic configuration for internal use.
23966+ When aufs supports Magic SysRq or /proc, enabled automatically.
23967+
4a4d8108
AM
23968+config AUFS_HNOTIFY
23969+ bool "Detect direct branch access (bypassing aufs)"
23970+ help
23971+ If you want to modify files on branches directly, eg. bypassing aufs,
23972+ and want aufs to detect the changes of them fully, then enable this
23973+ option and use 'udba=notify' mount option.
7f207e10 23974+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
23975+ It will have a negative impact to the performance.
23976+ See detail in aufs.5.
dece6358 23977+
4a4d8108
AM
23978+choice
23979+ prompt "method" if AUFS_HNOTIFY
23980+ default AUFS_HFSNOTIFY
23981+config AUFS_HFSNOTIFY
23982+ bool "fsnotify"
23983+ select FSNOTIFY
4a4d8108 23984+endchoice
1facf9fc 23985+
4a4d8108
AM
23986+config AUFS_EXPORT
23987+ bool "NFS-exportable aufs"
2cbb1c4b 23988+ depends on EXPORTFS
4a4d8108
AM
23989+ help
23990+ If you want to export your mounted aufs via NFS, then enable this
23991+ option. There are several requirements for this configuration.
23992+ See detail in aufs.5.
1facf9fc 23993+
4a4d8108
AM
23994+config AUFS_INO_T_64
23995+ bool
23996+ depends on AUFS_EXPORT
23997+ depends on 64BIT && !(ALPHA || S390)
23998+ default y
23999+ help
24000+ Automatic configuration for internal use.
24001+ /* typedef unsigned long/int __kernel_ino_t */
24002+ /* alpha and s390x are int */
1facf9fc 24003+
c1595e42
JR
24004+config AUFS_XATTR
24005+ bool "support for XATTR/EA (including Security Labels)"
24006+ help
24007+ If your branch fs supports XATTR/EA and you want to make them
24008+ available in aufs too, then enable this opsion and specify the
24009+ branch attributes for EA.
24010+ See detail in aufs.5.
24011+
076b876e
AM
24012+config AUFS_FHSM
24013+ bool "File-based Hierarchical Storage Management"
24014+ help
24015+ Hierarchical Storage Management (or HSM) is a well-known feature
24016+ in the storage world. Aufs provides this feature as file-based.
24017+ with multiple branches.
24018+ These multiple branches are prioritized, ie. the topmost one
24019+ should be the fastest drive and be used heavily.
24020+
4a4d8108
AM
24021+config AUFS_RDU
24022+ bool "Readdir in userspace"
24023+ help
24024+ Aufs has two methods to provide a merged view for a directory,
24025+ by a user-space library and by kernel-space natively. The latter
24026+ is always enabled but sometimes large and slow.
24027+ If you enable this option, install the library in aufs2-util
24028+ package, and set some environment variables for your readdir(3),
24029+ then the work will be handled in user-space which generally
24030+ shows better performance in most cases.
24031+ See detail in aufs.5.
1facf9fc 24032+
8b6a4947
AM
24033+config AUFS_DIRREN
24034+ bool "Workaround for rename(2)-ing a directory"
24035+ help
24036+ By default, aufs returns EXDEV error in renameing a dir who has
24037+ his child on the lower branch, since it is a bad idea to issue
24038+ rename(2) internally for every lower branch. But user may not
24039+ accept this behaviour. So here is a workaround to allow such
24040+ rename(2) and store some extra infromation on the writable
24041+ branch. Obviously this costs high (and I don't like it).
24042+ To use this feature, you need to enable this configuration AND
24043+ to specify the mount option `dirren.'
24044+ See details in aufs.5 and the design documents.
24045+
4a4d8108
AM
24046+config AUFS_SHWH
24047+ bool "Show whiteouts"
24048+ help
24049+ If you want to make the whiteouts in aufs visible, then enable
24050+ this option and specify 'shwh' mount option. Although it may
24051+ sounds like philosophy or something, but in technically it
24052+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 24053+
4a4d8108
AM
24054+config AUFS_BR_RAMFS
24055+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
24056+ help
24057+ If you want to use ramfs as an aufs branch fs, then enable this
24058+ option. Generally tmpfs is recommended.
24059+ Aufs prohibited them to be a branch fs by default, because
24060+ initramfs becomes unusable after switch_root or something
24061+ generally. If you sets initramfs as an aufs branch and boot your
24062+ system by switch_root, you will meet a problem easily since the
24063+ files in initramfs may be inaccessible.
24064+ Unless you are going to use ramfs as an aufs branch fs without
24065+ switch_root or something, leave it N.
1facf9fc 24066+
4a4d8108
AM
24067+config AUFS_BR_FUSE
24068+ bool "Fuse fs as an aufs branch"
24069+ depends on FUSE_FS
24070+ select AUFS_POLL
24071+ help
24072+ If you want to use fuse-based userspace filesystem as an aufs
24073+ branch fs, then enable this option.
24074+ It implements the internal poll(2) operation which is
24075+ implemented by fuse only (curretnly).
1facf9fc 24076+
4a4d8108
AM
24077+config AUFS_POLL
24078+ bool
24079+ help
24080+ Automatic configuration for internal use.
1facf9fc 24081+
4a4d8108
AM
24082+config AUFS_BR_HFSPLUS
24083+ bool "Hfsplus as an aufs branch"
24084+ depends on HFSPLUS_FS
24085+ default y
24086+ help
24087+ If you want to use hfsplus fs as an aufs branch fs, then enable
24088+ this option. This option introduces a small overhead at
24089+ copying-up a file on hfsplus.
1facf9fc 24090+
4a4d8108
AM
24091+config AUFS_BDEV_LOOP
24092+ bool
24093+ depends on BLK_DEV_LOOP
24094+ default y
24095+ help
24096+ Automatic configuration for internal use.
24097+ Convert =[ym] into =y.
1308ab2a 24098+
4a4d8108
AM
24099+config AUFS_DEBUG
24100+ bool "Debug aufs"
24101+ help
24102+ Enable this to compile aufs internal debug code.
24103+ It will have a negative impact to the performance.
24104+
24105+config AUFS_MAGIC_SYSRQ
24106+ bool
24107+ depends on AUFS_DEBUG && MAGIC_SYSRQ
24108+ default y
24109+ help
24110+ Automatic configuration for internal use.
24111+ When aufs supports Magic SysRq, enabled automatically.
24112+endif
acd2b654 24113diff -urN /usr/share/empty/fs/aufs/lcnt.h linux/fs/aufs/lcnt.h
fbc438ed
JR
24114--- /usr/share/empty/fs/aufs/lcnt.h 1970-01-01 08:00:00.000000000 +0800
24115+++ linux/fs/aufs/lcnt.h 2019-07-11 21:21:54.382384486 +0800
acd2b654
AM
24116@@ -0,0 +1,186 @@
24117+/* SPDX-License-Identifier: GPL-2.0 */
24118+/*
ba1aed25 24119+ * Copyright (C) 2018-2019 Junjiro R. Okajima
acd2b654
AM
24120+ *
24121+ * This program, aufs is free software; you can redistribute it and/or modify
24122+ * it under the terms of the GNU General Public License as published by
24123+ * the Free Software Foundation; either version 2 of the License, or
24124+ * (at your option) any later version.
24125+ *
24126+ * This program is distributed in the hope that it will be useful,
24127+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24128+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24129+ * GNU General Public License for more details.
24130+ *
24131+ * You should have received a copy of the GNU General Public License
24132+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24133+ */
24134+
24135+/*
24136+ * simple long counter wrapper
24137+ */
24138+
24139+#ifndef __AUFS_LCNT_H__
24140+#define __AUFS_LCNT_H__
24141+
24142+#ifdef __KERNEL__
24143+
24144+#include "debug.h"
24145+
24146+#define AuLCntATOMIC 1
24147+#define AuLCntPCPUCNT 2
24148+/*
24149+ * why does percpu_refcount require extra synchronize_rcu()s in
24150+ * au_br_do_free()
24151+ */
24152+#define AuLCntPCPUREF 3
24153+
24154+/* #define AuLCntChosen AuLCntATOMIC */
24155+#define AuLCntChosen AuLCntPCPUCNT
24156+/* #define AuLCntChosen AuLCntPCPUREF */
24157+
24158+#if AuLCntChosen == AuLCntATOMIC
24159+#include <linux/atomic.h>
24160+
24161+typedef atomic_long_t au_lcnt_t;
24162+
24163+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24164+{
24165+ atomic_long_set(cnt, 0);
24166+ return 0;
24167+}
24168+
24169+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24170+{
24171+ /* empty */
24172+}
24173+
24174+static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused,
24175+ int do_sync __maybe_unused)
24176+{
24177+ /* empty */
24178+}
24179+
24180+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24181+{
24182+ atomic_long_inc(cnt);
24183+}
24184+
24185+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24186+{
24187+ atomic_long_dec(cnt);
24188+}
24189+
24190+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24191+{
24192+ return atomic_long_read(cnt);
24193+}
24194+#endif
24195+
24196+#if AuLCntChosen == AuLCntPCPUCNT
24197+#include <linux/percpu_counter.h>
24198+
24199+typedef struct percpu_counter au_lcnt_t;
24200+
24201+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24202+{
24203+ return percpu_counter_init(cnt, 0, GFP_NOFS);
24204+}
24205+
24206+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24207+{
24208+ /* empty */
24209+}
24210+
24211+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused)
24212+{
24213+ percpu_counter_destroy(cnt);
24214+}
24215+
24216+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24217+{
24218+ percpu_counter_inc(cnt);
24219+}
24220+
24221+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24222+{
24223+ percpu_counter_dec(cnt);
24224+}
24225+
24226+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24227+{
24228+ s64 n;
24229+
24230+ n = percpu_counter_sum(cnt);
24231+ BUG_ON(n < 0);
24232+ if (LONG_MAX != LLONG_MAX
24233+ && n > LONG_MAX)
24234+ AuWarn1("%s\n", "wrap-around");
24235+
24236+ return n;
24237+}
24238+#endif
24239+
24240+#if AuLCntChosen == AuLCntPCPUREF
24241+#include <linux/percpu-refcount.h>
24242+
24243+typedef struct percpu_ref au_lcnt_t;
24244+
24245+static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release)
24246+{
24247+ if (!release)
24248+ release = percpu_ref_exit;
24249+ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS);
24250+}
24251+
24252+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24253+{
24254+ synchronize_rcu();
24255+}
24256+
24257+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync)
24258+{
24259+ percpu_ref_kill(cnt);
24260+ if (do_sync)
24261+ au_lcnt_wait_for_fin(cnt);
24262+}
24263+
24264+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24265+{
24266+ percpu_ref_get(cnt);
24267+}
24268+
24269+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24270+{
24271+ percpu_ref_put(cnt);
24272+}
24273+
24274+/*
24275+ * avoid calling this func as possible.
24276+ */
24277+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev)
24278+{
24279+ long l;
24280+
24281+ percpu_ref_switch_to_atomic_sync(cnt);
24282+ l = atomic_long_read(&cnt->count);
24283+ if (do_rev)
24284+ percpu_ref_switch_to_percpu(cnt);
24285+
24286+ /* percpu_ref is initialized by 1 instead of 0 */
24287+ return l - 1;
24288+}
24289+#endif
24290+
24291+#ifdef CONFIG_AUFS_DEBUG
24292+#define AuLCntZero(val) do { \
24293+ long l = val; \
24294+ if (l) \
24295+ AuDbg("%s = %ld\n", #val, l); \
24296+} while (0)
24297+#else
24298+#define AuLCntZero(val) do {} while (0)
24299+#endif
24300+
24301+#endif /* __KERNEL__ */
24302+#endif /* __AUFS_LCNT_H__ */
7f207e10 24303diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
fbc438ed
JR
24304--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 08:00:00.000000000 +0800
24305+++ linux/fs/aufs/loop.c 2019-07-11 21:21:54.382384486 +0800
062440b3 24306@@ -0,0 +1,148 @@
cd7a4cd9 24307+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24308+/*
ba1aed25 24309+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 24310+ *
24311+ * This program, aufs is free software; you can redistribute it and/or modify
24312+ * it under the terms of the GNU General Public License as published by
24313+ * the Free Software Foundation; either version 2 of the License, or
24314+ * (at your option) any later version.
dece6358
AM
24315+ *
24316+ * This program is distributed in the hope that it will be useful,
24317+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24318+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24319+ * GNU General Public License for more details.
24320+ *
24321+ * You should have received a copy of the GNU General Public License
523b37e3 24322+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24323+ */
24324+
24325+/*
24326+ * support for loopback block device as a branch
24327+ */
24328+
1facf9fc 24329+#include "aufs.h"
24330+
392086de
AM
24331+/* added into drivers/block/loop.c */
24332+static struct file *(*backing_file_func)(struct super_block *sb);
24333+
1facf9fc 24334+/*
24335+ * test if two lower dentries have overlapping branches.
24336+ */
b752ccd1 24337+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 24338+{
b752ccd1 24339+ struct super_block *h_sb;
392086de
AM
24340+ struct file *backing_file;
24341+
24342+ if (unlikely(!backing_file_func)) {
24343+ /* don't load "loop" module here */
24344+ backing_file_func = symbol_get(loop_backing_file);
24345+ if (unlikely(!backing_file_func))
24346+ /* "loop" module is not loaded */
24347+ return 0;
24348+ }
1facf9fc 24349+
b752ccd1 24350+ h_sb = h_adding->d_sb;
392086de
AM
24351+ backing_file = backing_file_func(h_sb);
24352+ if (!backing_file)
1facf9fc 24353+ return 0;
24354+
2000de60 24355+ h_adding = backing_file->f_path.dentry;
b752ccd1
AM
24356+ /*
24357+ * h_adding can be local NFS.
24358+ * in this case aufs cannot detect the loop.
24359+ */
24360+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 24361+ return 1;
b752ccd1 24362+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 24363+}
24364+
24365+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
24366+int au_test_loopback_kthread(void)
24367+{
b752ccd1
AM
24368+ int ret;
24369+ struct task_struct *tsk = current;
a2a7ad62 24370+ char c, comm[sizeof(tsk->comm)];
b752ccd1
AM
24371+
24372+ ret = 0;
24373+ if (tsk->flags & PF_KTHREAD) {
a2a7ad62
AM
24374+ get_task_comm(comm, tsk);
24375+ c = comm[4];
b752ccd1 24376+ ret = ('0' <= c && c <= '9'
a2a7ad62 24377+ && !strncmp(comm, "loop", 4));
b752ccd1 24378+ }
1facf9fc 24379+
b752ccd1 24380+ return ret;
1facf9fc 24381+}
87a755f4
AM
24382+
24383+/* ---------------------------------------------------------------------- */
24384+
24385+#define au_warn_loopback_step 16
24386+static int au_warn_loopback_nelem = au_warn_loopback_step;
24387+static unsigned long *au_warn_loopback_array;
24388+
24389+void au_warn_loopback(struct super_block *h_sb)
24390+{
24391+ int i, new_nelem;
24392+ unsigned long *a, magic;
24393+ static DEFINE_SPINLOCK(spin);
24394+
24395+ magic = h_sb->s_magic;
24396+ spin_lock(&spin);
24397+ a = au_warn_loopback_array;
24398+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
24399+ if (a[i] == magic) {
24400+ spin_unlock(&spin);
24401+ return;
24402+ }
24403+
24404+ /* h_sb is new to us, print it */
24405+ if (i < au_warn_loopback_nelem) {
24406+ a[i] = magic;
24407+ goto pr;
24408+ }
24409+
24410+ /* expand the array */
24411+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
24412+ a = au_kzrealloc(au_warn_loopback_array,
24413+ au_warn_loopback_nelem * sizeof(unsigned long),
e2f27e51
AM
24414+ new_nelem * sizeof(unsigned long), GFP_ATOMIC,
24415+ /*may_shrink*/0);
87a755f4
AM
24416+ if (a) {
24417+ au_warn_loopback_nelem = new_nelem;
24418+ au_warn_loopback_array = a;
24419+ a[i] = magic;
24420+ goto pr;
24421+ }
24422+
24423+ spin_unlock(&spin);
24424+ AuWarn1("realloc failed, ignored\n");
24425+ return;
24426+
24427+pr:
24428+ spin_unlock(&spin);
0c3ec466
AM
24429+ pr_warn("you may want to try another patch for loopback file "
24430+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
24431+}
24432+
24433+int au_loopback_init(void)
24434+{
24435+ int err;
24436+ struct super_block *sb __maybe_unused;
24437+
fbc438ed 24438+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array));
87a755f4
AM
24439+
24440+ err = 0;
24441+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
24442+ sizeof(unsigned long), GFP_NOFS);
24443+ if (unlikely(!au_warn_loopback_array))
24444+ err = -ENOMEM;
24445+
24446+ return err;
24447+}
24448+
24449+void au_loopback_fin(void)
24450+{
79b8bda9
AM
24451+ if (backing_file_func)
24452+ symbol_put(loop_backing_file);
9f237c51 24453+ au_kfree_try_rcu(au_warn_loopback_array);
87a755f4 24454+}
7f207e10 24455diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
fbc438ed
JR
24456--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 08:00:00.000000000 +0800
24457+++ linux/fs/aufs/loop.h 2019-07-11 21:21:54.382384486 +0800
eca801bf 24458@@ -0,0 +1,55 @@
062440b3 24459+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24460+/*
ba1aed25 24461+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 24462+ *
24463+ * This program, aufs is free software; you can redistribute it and/or modify
24464+ * it under the terms of the GNU General Public License as published by
24465+ * the Free Software Foundation; either version 2 of the License, or
24466+ * (at your option) any later version.
dece6358
AM
24467+ *
24468+ * This program is distributed in the hope that it will be useful,
24469+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24470+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24471+ * GNU General Public License for more details.
24472+ *
24473+ * You should have received a copy of the GNU General Public License
523b37e3 24474+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24475+ */
24476+
24477+/*
24478+ * support for loopback mount as a branch
24479+ */
24480+
24481+#ifndef __AUFS_LOOP_H__
24482+#define __AUFS_LOOP_H__
24483+
24484+#ifdef __KERNEL__
24485+
dece6358
AM
24486+struct dentry;
24487+struct super_block;
1facf9fc 24488+
24489+#ifdef CONFIG_AUFS_BDEV_LOOP
392086de
AM
24490+/* drivers/block/loop.c */
24491+struct file *loop_backing_file(struct super_block *sb);
24492+
1facf9fc 24493+/* loop.c */
b752ccd1 24494+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 24495+int au_test_loopback_kthread(void);
87a755f4
AM
24496+void au_warn_loopback(struct super_block *h_sb);
24497+
24498+int au_loopback_init(void);
24499+void au_loopback_fin(void);
1facf9fc 24500+#else
83b672a5 24501+AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf 24502+
4a4d8108 24503+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 24504+ struct dentry *h_adding)
4a4d8108 24505+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
24506+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
24507+
24508+AuStubInt0(au_loopback_init, void)
24509+AuStubVoid(au_loopback_fin, void)
1facf9fc 24510+#endif /* BLK_DEV_LOOP */
24511+
24512+#endif /* __KERNEL__ */
24513+#endif /* __AUFS_LOOP_H__ */
7f207e10 24514diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
fbc438ed
JR
24515--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 08:00:00.000000000 +0800
24516+++ linux/fs/aufs/magic.mk 2019-07-11 21:21:54.382384486 +0800
2121bcd9
AM
24517@@ -0,0 +1,31 @@
24518+# SPDX-License-Identifier: GPL-2.0
1facf9fc 24519+
24520+# defined in ${srctree}/fs/fuse/inode.c
24521+# tristate
24522+ifdef CONFIG_FUSE_FS
24523+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
24524+endif
24525+
1facf9fc 24526+# defined in ${srctree}/fs/xfs/xfs_sb.h
24527+# tristate
24528+ifdef CONFIG_XFS_FS
24529+ccflags-y += -DXFS_SB_MAGIC=0x58465342
24530+endif
24531+
24532+# defined in ${srctree}/fs/configfs/mount.c
24533+# tristate
24534+ifdef CONFIG_CONFIGFS_FS
24535+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
24536+endif
24537+
1facf9fc 24538+# defined in ${srctree}/fs/ubifs/ubifs.h
24539+# tristate
24540+ifdef CONFIG_UBIFS_FS
24541+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
24542+endif
4a4d8108
AM
24543+
24544+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
24545+# tristate
24546+ifdef CONFIG_HFSPLUS_FS
24547+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
24548+endif
7f207e10 24549diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
fbc438ed
JR
24550--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 08:00:00.000000000 +0800
24551+++ linux/fs/aufs/Makefile 2019-07-11 21:21:54.379051070 +0800
2121bcd9
AM
24552@@ -0,0 +1,46 @@
24553+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
24554+
24555+include ${src}/magic.mk
24556+ifeq (${CONFIG_AUFS_FS},m)
24557+include ${src}/conf.mk
24558+endif
24559+-include ${src}/priv_def.mk
24560+
24561+# cf. include/linux/kernel.h
24562+# enable pr_debug
24563+ccflags-y += -DDEBUG
f6c5ef8b
AM
24564+# sparse requires the full pathname
24565+ifdef M
523b37e3 24566+ccflags-y += -include ${M}/../../include/uapi/linux/aufs_type.h
f6c5ef8b 24567+else
523b37e3 24568+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h
f6c5ef8b 24569+endif
4a4d8108
AM
24570+
24571+obj-$(CONFIG_AUFS_FS) += aufs.o
24572+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
24573+ wkq.o vfsub.o dcsub.o \
e49829fe 24574+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
24575+ dinfo.o dentry.o \
24576+ dynop.o \
24577+ finfo.o file.o f_op.o \
24578+ dir.o vdir.o \
24579+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
c2b27bf2 24580+ mvdown.o ioctl.o
4a4d8108
AM
24581+
24582+# all are boolean
e49829fe 24583+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
24584+aufs-$(CONFIG_SYSFS) += sysfs.o
24585+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
24586+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
24587+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
24588+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108 24589+aufs-$(CONFIG_AUFS_EXPORT) += export.o
c1595e42
JR
24590+aufs-$(CONFIG_AUFS_XATTR) += xattr.o
24591+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
8b6a4947 24592+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o
076b876e 24593+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o
4a4d8108
AM
24594+aufs-$(CONFIG_AUFS_POLL) += poll.o
24595+aufs-$(CONFIG_AUFS_RDU) += rdu.o
4a4d8108
AM
24596+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
24597+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
24598+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10 24599diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
fbc438ed
JR
24600--- /usr/share/empty/fs/aufs/module.c 1970-01-01 08:00:00.000000000 +0800
24601+++ linux/fs/aufs/module.c 2019-07-11 21:21:54.382384486 +0800
062440b3 24602@@ -0,0 +1,273 @@
cd7a4cd9 24603+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24604+/*
ba1aed25 24605+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 24606+ *
24607+ * This program, aufs is free software; you can redistribute it and/or modify
24608+ * it under the terms of the GNU General Public License as published by
24609+ * the Free Software Foundation; either version 2 of the License, or
24610+ * (at your option) any later version.
dece6358
AM
24611+ *
24612+ * This program is distributed in the hope that it will be useful,
24613+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24614+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24615+ * GNU General Public License for more details.
24616+ *
24617+ * You should have received a copy of the GNU General Public License
523b37e3 24618+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24619+ */
24620+
24621+/*
24622+ * module global variables and operations
24623+ */
24624+
24625+#include <linux/module.h>
24626+#include <linux/seq_file.h>
24627+#include "aufs.h"
24628+
e2f27e51
AM
24629+/* shrinkable realloc */
24630+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink)
1facf9fc 24631+{
e2f27e51
AM
24632+ size_t sz;
24633+ int diff;
1facf9fc 24634+
e2f27e51
AM
24635+ sz = 0;
24636+ diff = -1;
24637+ if (p) {
24638+#if 0 /* unused */
24639+ if (!new_sz) {
9f237c51 24640+ au_kfree_rcu(p);
e2f27e51
AM
24641+ p = NULL;
24642+ goto out;
24643+ }
24644+#else
24645+ AuDebugOn(!new_sz);
24646+#endif
24647+ sz = ksize(p);
24648+ diff = au_kmidx_sub(sz, new_sz);
24649+ }
24650+ if (sz && !diff)
24651+ goto out;
24652+
24653+ if (sz < new_sz)
24654+ /* expand or SLOB */
24655+ p = krealloc(p, new_sz, gfp);
24656+ else if (new_sz < sz && may_shrink) {
24657+ /* shrink */
24658+ void *q;
24659+
24660+ q = kmalloc(new_sz, gfp);
24661+ if (q) {
24662+ if (p) {
24663+ memcpy(q, p, new_sz);
9f237c51 24664+ au_kfree_try_rcu(p);
e2f27e51
AM
24665+ }
24666+ p = q;
24667+ } else
24668+ p = NULL;
24669+ }
24670+
24671+out:
24672+ return p;
24673+}
24674+
24675+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24676+ int may_shrink)
24677+{
24678+ p = au_krealloc(p, new_sz, gfp, may_shrink);
24679+ if (p && new_sz > nused)
1facf9fc 24680+ memset(p + nused, 0, new_sz - nused);
24681+ return p;
24682+}
24683+
24684+/* ---------------------------------------------------------------------- */
1facf9fc 24685+/*
24686+ * aufs caches
24687+ */
1c60b727 24688+struct kmem_cache *au_cache[AuCache_Last];
5afbbe0d
AM
24689+
24690+static void au_cache_fin(void)
24691+{
24692+ int i;
24693+
24694+ /*
24695+ * Make sure all delayed rcu free inodes are flushed before we
24696+ * destroy cache.
24697+ */
24698+ rcu_barrier();
24699+
24700+ /* excluding AuCache_HNOTIFY */
24701+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
24702+ for (i = 0; i < AuCache_HNOTIFY; i++) {
1c60b727
AM
24703+ kmem_cache_destroy(au_cache[i]);
24704+ au_cache[i] = NULL;
5afbbe0d
AM
24705+ }
24706+}
24707+
1facf9fc 24708+static int __init au_cache_init(void)
24709+{
1c60b727
AM
24710+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
24711+ if (au_cache[AuCache_DINFO])
027c5e7a 24712+ /* SLAB_DESTROY_BY_RCU */
1c60b727 24713+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
f0c0a007 24714+ au_icntnr_init_once);
1c60b727
AM
24715+ if (au_cache[AuCache_ICNTNR])
24716+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo,
f0c0a007 24717+ au_fi_init_once);
1c60b727
AM
24718+ if (au_cache[AuCache_FINFO])
24719+ au_cache[AuCache_VDIR] = AuCache(au_vdir);
24720+ if (au_cache[AuCache_VDIR])
24721+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
24722+ if (au_cache[AuCache_DEHSTR])
1facf9fc 24723+ return 0;
24724+
5afbbe0d 24725+ au_cache_fin();
1facf9fc 24726+ return -ENOMEM;
24727+}
24728+
1facf9fc 24729+/* ---------------------------------------------------------------------- */
24730+
24731+int au_dir_roflags;
24732+
e49829fe 24733+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
24734+/*
24735+ * iterate_supers_type() doesn't protect us from
24736+ * remounting (branch management)
24737+ */
8b6a4947 24738+struct hlist_bl_head au_sbilist;
e49829fe
JR
24739+#endif
24740+
1facf9fc 24741+/*
24742+ * functions for module interface.
24743+ */
24744+MODULE_LICENSE("GPL");
24745+/* MODULE_LICENSE("GPL v2"); */
dece6358 24746+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 24747+MODULE_DESCRIPTION(AUFS_NAME
24748+ " -- Advanced multi layered unification filesystem");
24749+MODULE_VERSION(AUFS_VERSION);
c06a8ce3 24750+MODULE_ALIAS_FS(AUFS_NAME);
1facf9fc 24751+
1facf9fc 24752+/* this module parameter has no meaning when SYSFS is disabled */
24753+int sysaufs_brs = 1;
24754+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
cd7a4cd9 24755+module_param_named(brs, sysaufs_brs, int, 0444);
1facf9fc 24756+
076b876e 24757+/* this module parameter has no meaning when USER_NS is disabled */
8cdd5066 24758+bool au_userns;
076b876e 24759+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns");
cd7a4cd9 24760+module_param_named(allow_userns, au_userns, bool, 0444);
076b876e 24761+
1facf9fc 24762+/* ---------------------------------------------------------------------- */
24763+
24764+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
24765+
24766+int au_seq_path(struct seq_file *seq, struct path *path)
24767+{
79b8bda9
AM
24768+ int err;
24769+
24770+ err = seq_path(seq, path, au_esc_chars);
1c60b727 24771+ if (err >= 0)
79b8bda9 24772+ err = 0;
1c60b727 24773+ else
79b8bda9
AM
24774+ err = -ENOMEM;
24775+
24776+ return err;
1facf9fc 24777+}
24778+
24779+/* ---------------------------------------------------------------------- */
24780+
24781+static int __init aufs_init(void)
24782+{
24783+ int err, i;
24784+ char *p;
24785+
24786+ p = au_esc_chars;
24787+ for (i = 1; i <= ' '; i++)
24788+ *p++ = i;
24789+ *p++ = '\\';
24790+ *p++ = '\x7f';
24791+ *p = 0;
24792+
24793+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
24794+
b95c5147
AM
24795+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop));
24796+ for (i = 0; i < AuIop_Last; i++)
24797+ aufs_iop_nogetattr[i].getattr = NULL;
24798+
1c60b727 24799+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */
f0c0a007 24800+
e49829fe 24801+ au_sbilist_init();
1facf9fc 24802+ sysaufs_brs_init();
24803+ au_debug_init();
4a4d8108 24804+ au_dy_init();
1facf9fc 24805+ err = sysaufs_init();
24806+ if (unlikely(err))
24807+ goto out;
062440b3 24808+ err = dbgaufs_init();
4f0767ce 24809+ if (unlikely(err))
953406b4 24810+ goto out_sysaufs;
062440b3
AM
24811+ err = au_procfs_init();
24812+ if (unlikely(err))
24813+ goto out_dbgaufs;
e49829fe
JR
24814+ err = au_wkq_init();
24815+ if (unlikely(err))
24816+ goto out_procfs;
87a755f4 24817+ err = au_loopback_init();
1facf9fc 24818+ if (unlikely(err))
24819+ goto out_wkq;
87a755f4
AM
24820+ err = au_hnotify_init();
24821+ if (unlikely(err))
24822+ goto out_loopback;
1facf9fc 24823+ err = au_sysrq_init();
24824+ if (unlikely(err))
24825+ goto out_hin;
24826+ err = au_cache_init();
24827+ if (unlikely(err))
24828+ goto out_sysrq;
076b876e
AM
24829+
24830+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0;
1facf9fc 24831+ err = register_filesystem(&aufs_fs_type);
24832+ if (unlikely(err))
24833+ goto out_cache;
076b876e 24834+
4a4d8108
AM
24835+ /* since we define pr_fmt, call printk directly */
24836+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 24837+ goto out; /* success */
24838+
4f0767ce 24839+out_cache:
1facf9fc 24840+ au_cache_fin();
4f0767ce 24841+out_sysrq:
1facf9fc 24842+ au_sysrq_fin();
4f0767ce 24843+out_hin:
4a4d8108 24844+ au_hnotify_fin();
87a755f4
AM
24845+out_loopback:
24846+ au_loopback_fin();
4f0767ce 24847+out_wkq:
1facf9fc 24848+ au_wkq_fin();
e49829fe
JR
24849+out_procfs:
24850+ au_procfs_fin();
062440b3
AM
24851+out_dbgaufs:
24852+ dbgaufs_fin();
4f0767ce 24853+out_sysaufs:
1facf9fc 24854+ sysaufs_fin();
4a4d8108 24855+ au_dy_fin();
4f0767ce 24856+out:
1facf9fc 24857+ return err;
24858+}
24859+
24860+static void __exit aufs_exit(void)
24861+{
24862+ unregister_filesystem(&aufs_fs_type);
24863+ au_cache_fin();
24864+ au_sysrq_fin();
4a4d8108 24865+ au_hnotify_fin();
87a755f4 24866+ au_loopback_fin();
1facf9fc 24867+ au_wkq_fin();
e49829fe 24868+ au_procfs_fin();
062440b3 24869+ dbgaufs_fin();
1facf9fc 24870+ sysaufs_fin();
4a4d8108 24871+ au_dy_fin();
1facf9fc 24872+}
24873+
24874+module_init(aufs_init);
24875+module_exit(aufs_exit);
7f207e10 24876diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
fbc438ed
JR
24877--- /usr/share/empty/fs/aufs/module.h 1970-01-01 08:00:00.000000000 +0800
24878+++ linux/fs/aufs/module.h 2019-07-11 21:21:54.382384486 +0800
9f237c51 24879@@ -0,0 +1,166 @@
062440b3 24880+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24881+/*
ba1aed25 24882+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 24883+ *
24884+ * This program, aufs is free software; you can redistribute it and/or modify
24885+ * it under the terms of the GNU General Public License as published by
24886+ * the Free Software Foundation; either version 2 of the License, or
24887+ * (at your option) any later version.
dece6358
AM
24888+ *
24889+ * This program is distributed in the hope that it will be useful,
24890+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24891+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24892+ * GNU General Public License for more details.
24893+ *
24894+ * You should have received a copy of the GNU General Public License
523b37e3 24895+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24896+ */
24897+
24898+/*
24899+ * module initialization and module-global
24900+ */
24901+
24902+#ifndef __AUFS_MODULE_H__
24903+#define __AUFS_MODULE_H__
24904+
24905+#ifdef __KERNEL__
24906+
24907+#include <linux/slab.h>
9f237c51
AM
24908+#include "debug.h"
24909+#include "dentry.h"
24910+#include "dir.h"
24911+#include "file.h"
24912+#include "inode.h"
1facf9fc 24913+
dece6358
AM
24914+struct path;
24915+struct seq_file;
24916+
1facf9fc 24917+/* module parameters */
1facf9fc 24918+extern int sysaufs_brs;
8cdd5066 24919+extern bool au_userns;
1facf9fc 24920+
24921+/* ---------------------------------------------------------------------- */
24922+
24923+extern int au_dir_roflags;
24924+
e2f27e51
AM
24925+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink);
24926+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24927+ int may_shrink);
24928+
9f237c51
AM
24929+/*
24930+ * Comparing the size of the object with sizeof(struct rcu_head)
24931+ * case 1: object is always larger
24932+ * --> au_kfree_rcu() or au_kfree_do_rcu()
24933+ * case 2: object is always smaller
24934+ * --> au_kfree_small()
24935+ * case 3: object can be any size
24936+ * --> au_kfree_try_rcu()
24937+ */
24938+
24939+static inline void au_kfree_do_rcu(const void *p)
24940+{
24941+ struct {
24942+ struct rcu_head rcu;
24943+ } *a = (void *)p;
24944+
24945+ kfree_rcu(a, rcu);
24946+}
24947+
24948+#define au_kfree_rcu(_p) do { \
24949+ typeof(_p) p = (_p); \
24950+ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \
24951+ if (p) \
24952+ au_kfree_do_rcu(p); \
24953+ } while (0)
24954+
24955+#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head))
24956+#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p)))
24957+
24958+static inline void au_kfree_try_rcu(const void *p)
24959+{
24960+ if (!p)
24961+ return;
24962+ if (au_kfree_sz_test(p))
24963+ au_kfree_do_rcu(p);
24964+ else
24965+ kfree(p);
24966+}
24967+
24968+static inline void au_kfree_small(const void *p)
24969+{
24970+ if (!p)
24971+ return;
24972+ AuDebugOn(au_kfree_sz_test(p));
24973+ kfree(p);
24974+}
24975+
e2f27e51
AM
24976+static inline int au_kmidx_sub(size_t sz, size_t new_sz)
24977+{
24978+#ifndef CONFIG_SLOB
24979+ return kmalloc_index(sz) - kmalloc_index(new_sz);
24980+#else
24981+ return -1; /* SLOB is untested */
24982+#endif
24983+}
24984+
1facf9fc 24985+int au_seq_path(struct seq_file *seq, struct path *path);
24986+
e49829fe
JR
24987+#ifdef CONFIG_PROC_FS
24988+/* procfs.c */
24989+int __init au_procfs_init(void);
24990+void au_procfs_fin(void);
24991+#else
24992+AuStubInt0(au_procfs_init, void);
24993+AuStubVoid(au_procfs_fin, void);
24994+#endif
24995+
4f0767ce
JR
24996+/* ---------------------------------------------------------------------- */
24997+
1c60b727 24998+/* kmem cache */
1facf9fc 24999+enum {
25000+ AuCache_DINFO,
25001+ AuCache_ICNTNR,
25002+ AuCache_FINFO,
25003+ AuCache_VDIR,
25004+ AuCache_DEHSTR,
7eafdf33 25005+ AuCache_HNOTIFY, /* must be last */
1facf9fc 25006+ AuCache_Last
25007+};
25008+
1c60b727 25009+extern struct kmem_cache *au_cache[AuCache_Last];
f0c0a007 25010+
4a4d8108
AM
25011+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
25012+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
25013+#define AuCacheCtor(type, ctor) \
25014+ kmem_cache_create(#type, sizeof(struct type), \
25015+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 25016+
9f237c51
AM
25017+#define AuCacheFuncs(name, index) \
25018+ static inline struct au_##name *au_cache_alloc_##name(void) \
25019+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \
25020+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \
25021+ { kmem_cache_free(au_cache[AuCache_##index], p); } \
25022+ \
25023+ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \
25024+ { void *p = rcu; \
25025+ p -= offsetof(struct au_##name, rcu); \
25026+ kmem_cache_free(au_cache[AuCache_##index], p); } \
25027+ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \
25028+ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \
25029+ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \
25030+ \
25031+ static inline void au_cache_free_##name(struct au_##name *p) \
25032+ { /* au_cache_free_##name##_norcu(p); */ \
25033+ au_cache_free_##name##_rcu(p); }
1facf9fc 25034+
25035+AuCacheFuncs(dinfo, DINFO);
25036+AuCacheFuncs(icntnr, ICNTNR);
25037+AuCacheFuncs(finfo, FINFO);
25038+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
25039+AuCacheFuncs(vdir_dehstr, DEHSTR);
25040+#ifdef CONFIG_AUFS_HNOTIFY
25041+AuCacheFuncs(hnotify, HNOTIFY);
25042+#endif
1facf9fc 25043+
4a4d8108
AM
25044+#endif /* __KERNEL__ */
25045+#endif /* __AUFS_MODULE_H__ */
c2b27bf2 25046diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
fbc438ed
JR
25047--- /usr/share/empty/fs/aufs/mvdown.c 1970-01-01 08:00:00.000000000 +0800
25048+++ linux/fs/aufs/mvdown.c 2019-07-11 21:21:54.382384486 +0800
ba1aed25 25049@@ -0,0 +1,706 @@
cd7a4cd9 25050+// SPDX-License-Identifier: GPL-2.0
c2b27bf2 25051+/*
ba1aed25 25052+ * Copyright (C) 2011-2019 Junjiro R. Okajima
c2b27bf2
AM
25053+ *
25054+ * This program, aufs is free software; you can redistribute it and/or modify
25055+ * it under the terms of the GNU General Public License as published by
25056+ * the Free Software Foundation; either version 2 of the License, or
25057+ * (at your option) any later version.
25058+ *
25059+ * This program is distributed in the hope that it will be useful,
25060+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25061+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25062+ * GNU General Public License for more details.
25063+ *
25064+ * You should have received a copy of the GNU General Public License
523b37e3
AM
25065+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
25066+ */
25067+
25068+/*
25069+ * move-down, opposite of copy-up
c2b27bf2
AM
25070+ */
25071+
25072+#include "aufs.h"
25073+
c2b27bf2
AM
25074+struct au_mvd_args {
25075+ struct {
c2b27bf2
AM
25076+ struct super_block *h_sb;
25077+ struct dentry *h_parent;
25078+ struct au_hinode *hdir;
392086de 25079+ struct inode *h_dir, *h_inode;
c1595e42 25080+ struct au_pin pin;
c2b27bf2
AM
25081+ } info[AUFS_MVDOWN_NARRAY];
25082+
25083+ struct aufs_mvdown mvdown;
25084+ struct dentry *dentry, *parent;
25085+ struct inode *inode, *dir;
25086+ struct super_block *sb;
25087+ aufs_bindex_t bopq, bwh, bfound;
25088+ unsigned char rename_lock;
c2b27bf2
AM
25089+};
25090+
392086de 25091+#define mvd_errno mvdown.au_errno
076b876e
AM
25092+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex
25093+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid
25094+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex
25095+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid
c2b27bf2 25096+
392086de
AM
25097+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb
25098+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent
25099+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir
25100+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir
25101+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode
c1595e42 25102+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin
392086de
AM
25103+
25104+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb
25105+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent
25106+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir
25107+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir
25108+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode
c1595e42 25109+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin
c2b27bf2
AM
25110+
25111+#define AU_MVD_PR(flag, ...) do { \
25112+ if (flag) \
25113+ pr_err(__VA_ARGS__); \
25114+ } while (0)
25115+
076b876e
AM
25116+static int find_lower_writable(struct au_mvd_args *a)
25117+{
25118+ struct super_block *sb;
5afbbe0d 25119+ aufs_bindex_t bindex, bbot;
076b876e
AM
25120+ struct au_branch *br;
25121+
25122+ sb = a->sb;
25123+ bindex = a->mvd_bsrc;
5afbbe0d 25124+ bbot = au_sbbot(sb);
076b876e 25125+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER)
5afbbe0d 25126+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
25127+ br = au_sbr(sb, bindex);
25128+ if (au_br_fhsm(br->br_perm)
8b6a4947 25129+ && !sb_rdonly(au_br_sb(br)))
076b876e
AM
25130+ return bindex;
25131+ }
25132+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER))
5afbbe0d 25133+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
25134+ br = au_sbr(sb, bindex);
25135+ if (!au_br_rdonly(br))
25136+ return bindex;
25137+ }
25138+ else
5afbbe0d 25139+ for (bindex++; bindex <= bbot; bindex++) {
076b876e 25140+ br = au_sbr(sb, bindex);
8b6a4947 25141+ if (!sb_rdonly(au_br_sb(br))) {
076b876e
AM
25142+ if (au_br_rdonly(br))
25143+ a->mvdown.flags
25144+ |= AUFS_MVDOWN_ROLOWER_R;
25145+ return bindex;
25146+ }
25147+ }
25148+
25149+ return -1;
25150+}
25151+
c2b27bf2 25152+/* make the parent dir on bdst */
392086de 25153+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25154+{
25155+ int err;
25156+
25157+ err = 0;
25158+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc);
25159+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst);
25160+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc);
25161+ a->mvd_h_dst_parent = NULL;
5afbbe0d 25162+ if (au_dbbot(a->parent) >= a->mvd_bdst)
c2b27bf2
AM
25163+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
25164+ if (!a->mvd_h_dst_parent) {
25165+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst);
25166+ if (unlikely(err)) {
392086de 25167+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n");
c2b27bf2
AM
25168+ goto out;
25169+ }
25170+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
25171+ }
25172+
25173+out:
25174+ AuTraceErr(err);
25175+ return err;
25176+}
25177+
25178+/* lock them all */
392086de 25179+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25180+{
25181+ int err;
25182+ struct dentry *h_trap;
25183+
25184+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
25185+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
c1595e42
JR
25186+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
25187+ au_opt_udba(a->sb),
25188+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25189+ AuTraceErr(err);
25190+ if (unlikely(err)) {
25191+ AU_MVD_PR(dmsg, "pin_dst failed\n");
25192+ goto out;
25193+ }
25194+
c2b27bf2
AM
25195+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
25196+ a->rename_lock = 0;
c1595e42
JR
25197+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25198+ AuLsc_DI_PARENT, AuLsc_I_PARENT3,
25199+ au_opt_udba(a->sb),
25200+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25201+ err = au_do_pin(&a->mvd_pin_src);
25202+ AuTraceErr(err);
5527c038 25203+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25204+ if (unlikely(err)) {
25205+ AU_MVD_PR(dmsg, "pin_src failed\n");
25206+ goto out_dst;
25207+ }
25208+ goto out; /* success */
c2b27bf2
AM
25209+ }
25210+
c2b27bf2 25211+ a->rename_lock = 1;
c1595e42
JR
25212+ au_pin_hdir_unlock(&a->mvd_pin_dst);
25213+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25214+ au_opt_udba(a->sb),
25215+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25216+ AuTraceErr(err);
5527c038 25217+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25218+ if (unlikely(err)) {
25219+ AU_MVD_PR(dmsg, "pin_src failed\n");
25220+ au_pin_hdir_lock(&a->mvd_pin_dst);
25221+ goto out_dst;
25222+ }
25223+ au_pin_hdir_unlock(&a->mvd_pin_src);
c2b27bf2
AM
25224+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25225+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25226+ if (h_trap) {
25227+ err = (h_trap != a->mvd_h_src_parent);
25228+ if (err)
25229+ err = (h_trap != a->mvd_h_dst_parent);
25230+ }
25231+ BUG_ON(err); /* it should never happen */
c1595e42
JR
25232+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
25233+ err = -EBUSY;
25234+ AuTraceErr(err);
25235+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25236+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25237+ au_pin_hdir_lock(&a->mvd_pin_src);
25238+ au_unpin(&a->mvd_pin_src);
25239+ au_pin_hdir_lock(&a->mvd_pin_dst);
25240+ goto out_dst;
25241+ }
25242+ goto out; /* success */
c2b27bf2 25243+
c1595e42
JR
25244+out_dst:
25245+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25246+out:
25247+ AuTraceErr(err);
25248+ return err;
25249+}
25250+
392086de 25251+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2 25252+{
c1595e42
JR
25253+ if (!a->rename_lock)
25254+ au_unpin(&a->mvd_pin_src);
25255+ else {
c2b27bf2
AM
25256+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25257+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
c1595e42
JR
25258+ au_pin_hdir_lock(&a->mvd_pin_src);
25259+ au_unpin(&a->mvd_pin_src);
25260+ au_pin_hdir_lock(&a->mvd_pin_dst);
25261+ }
25262+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25263+}
25264+
25265+/* copy-down the file */
392086de 25266+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25267+{
25268+ int err;
25269+ struct au_cp_generic cpg = {
25270+ .dentry = a->dentry,
25271+ .bdst = a->mvd_bdst,
25272+ .bsrc = a->mvd_bsrc,
25273+ .len = -1,
c1595e42 25274+ .pin = &a->mvd_pin_dst,
c2b27bf2
AM
25275+ .flags = AuCpup_DTIME | AuCpup_HOPEN
25276+ };
25277+
25278+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
392086de
AM
25279+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25280+ au_fset_cpup(cpg.flags, OVERWRITE);
25281+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER)
25282+ au_fset_cpup(cpg.flags, RWDST);
c2b27bf2
AM
25283+ err = au_sio_cpdown_simple(&cpg);
25284+ if (unlikely(err))
392086de 25285+ AU_MVD_PR(dmsg, "cpdown failed\n");
c2b27bf2
AM
25286+
25287+ AuTraceErr(err);
25288+ return err;
25289+}
25290+
25291+/*
25292+ * unlink the whiteout on bdst if exist which may be created by UDBA while we
25293+ * were sleeping
25294+ */
392086de 25295+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25296+{
25297+ int err;
25298+ struct path h_path;
25299+ struct au_branch *br;
523b37e3 25300+ struct inode *delegated;
c2b27bf2
AM
25301+
25302+ br = au_sbr(a->sb, a->mvd_bdst);
25303+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
25304+ err = PTR_ERR(h_path.dentry);
25305+ if (IS_ERR(h_path.dentry)) {
392086de 25306+ AU_MVD_PR(dmsg, "wh_lkup failed\n");
c2b27bf2
AM
25307+ goto out;
25308+ }
25309+
25310+ err = 0;
5527c038 25311+ if (d_is_positive(h_path.dentry)) {
c2b27bf2 25312+ h_path.mnt = au_br_mnt(br);
523b37e3 25313+ delegated = NULL;
5527c038 25314+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path,
523b37e3
AM
25315+ &delegated, /*force*/0);
25316+ if (unlikely(err == -EWOULDBLOCK)) {
25317+ pr_warn("cannot retry for NFSv4 delegation"
25318+ " for an internal unlink\n");
25319+ iput(delegated);
25320+ }
c2b27bf2 25321+ if (unlikely(err))
392086de 25322+ AU_MVD_PR(dmsg, "wh_unlink failed\n");
c2b27bf2
AM
25323+ }
25324+ dput(h_path.dentry);
25325+
25326+out:
25327+ AuTraceErr(err);
25328+ return err;
25329+}
25330+
25331+/*
25332+ * unlink the topmost h_dentry
c2b27bf2 25333+ */
392086de 25334+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25335+{
25336+ int err;
25337+ struct path h_path;
523b37e3 25338+ struct inode *delegated;
c2b27bf2
AM
25339+
25340+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc);
25341+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc);
523b37e3
AM
25342+ delegated = NULL;
25343+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0);
25344+ if (unlikely(err == -EWOULDBLOCK)) {
25345+ pr_warn("cannot retry for NFSv4 delegation"
25346+ " for an internal unlink\n");
25347+ iput(delegated);
25348+ }
c2b27bf2 25349+ if (unlikely(err))
392086de 25350+ AU_MVD_PR(dmsg, "unlink failed\n");
c2b27bf2
AM
25351+
25352+ AuTraceErr(err);
25353+ return err;
25354+}
25355+
076b876e
AM
25356+/* Since mvdown succeeded, we ignore an error of this function */
25357+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a)
25358+{
25359+ int err;
25360+ struct au_branch *br;
25361+
25362+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED;
25363+ br = au_sbr(a->sb, a->mvd_bsrc);
25364+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs);
25365+ if (!err) {
25366+ br = au_sbr(a->sb, a->mvd_bdst);
25367+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id;
25368+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs);
25369+ }
25370+ if (!err)
25371+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED;
25372+ else
25373+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err);
25374+}
25375+
c2b27bf2
AM
25376+/*
25377+ * copy-down the file and unlink the bsrc file.
25378+ * - unlink the bdst whout if exist
25379+ * - copy-down the file (with whtmp name and rename)
25380+ * - unlink the bsrc file
25381+ */
392086de 25382+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25383+{
25384+ int err;
25385+
392086de 25386+ err = au_do_mkdir(dmsg, a);
c2b27bf2 25387+ if (!err)
392086de 25388+ err = au_do_lock(dmsg, a);
c2b27bf2
AM
25389+ if (unlikely(err))
25390+ goto out;
25391+
25392+ /*
25393+ * do not revert the activities we made on bdst since they should be
25394+ * harmless in aufs.
25395+ */
25396+
392086de 25397+ err = au_do_cpdown(dmsg, a);
c2b27bf2 25398+ if (!err)
392086de
AM
25399+ err = au_do_unlink_wh(dmsg, a);
25400+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
25401+ err = au_do_unlink(dmsg, a);
c2b27bf2
AM
25402+ if (unlikely(err))
25403+ goto out_unlock;
25404+
c1595e42
JR
25405+ AuDbg("%pd2, 0x%x, %d --> %d\n",
25406+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
076b876e
AM
25407+ if (find_lower_writable(a) < 0)
25408+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;
25409+
25410+ if (a->mvdown.flags & AUFS_MVDOWN_STFS)
25411+ au_do_stfs(dmsg, a);
25412+
c2b27bf2 25413+ /* maintain internal array */
392086de
AM
25414+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
25415+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
5afbbe0d 25416+ au_set_dbtop(a->dentry, a->mvd_bdst);
392086de 25417+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
5afbbe0d 25418+ au_set_ibtop(a->inode, a->mvd_bdst);
79b8bda9
AM
25419+ } else {
25420+ /* hide the lower */
25421+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
5afbbe0d 25422+ au_set_dbbot(a->dentry, a->mvd_bsrc);
79b8bda9 25423+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
5afbbe0d 25424+ au_set_ibbot(a->inode, a->mvd_bsrc);
392086de 25425+ }
5afbbe0d
AM
25426+ if (au_dbbot(a->dentry) < a->mvd_bdst)
25427+ au_set_dbbot(a->dentry, a->mvd_bdst);
25428+ if (au_ibbot(a->inode) < a->mvd_bdst)
25429+ au_set_ibbot(a->inode, a->mvd_bdst);
c2b27bf2
AM
25430+
25431+out_unlock:
392086de 25432+ au_do_unlock(dmsg, a);
c2b27bf2
AM
25433+out:
25434+ AuTraceErr(err);
25435+ return err;
25436+}
25437+
25438+/* ---------------------------------------------------------------------- */
25439+
c2b27bf2 25440+/* make sure the file is idle */
392086de 25441+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25442+{
25443+ int err, plinked;
c2b27bf2
AM
25444+
25445+ err = 0;
c2b27bf2 25446+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
5afbbe0d 25447+ if (au_dbtop(a->dentry) == a->mvd_bsrc
c1595e42 25448+ && au_dcount(a->dentry) == 1
c2b27bf2 25449+ && atomic_read(&a->inode->i_count) == 1
392086de 25450+ /* && a->mvd_h_src_inode->i_nlink == 1 */
c2b27bf2
AM
25451+ && (!plinked || !au_plink_test(a->inode))
25452+ && a->inode->i_nlink == 1)
25453+ goto out;
25454+
25455+ err = -EBUSY;
392086de 25456+ AU_MVD_PR(dmsg,
c1595e42 25457+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
5afbbe0d 25458+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry),
c2b27bf2 25459+ atomic_read(&a->inode->i_count), a->inode->i_nlink,
392086de 25460+ a->mvd_h_src_inode->i_nlink,
c2b27bf2
AM
25461+ plinked, plinked ? au_plink_test(a->inode) : 0);
25462+
25463+out:
25464+ AuTraceErr(err);
25465+ return err;
25466+}
25467+
25468+/* make sure the parent dir is fine */
392086de 25469+static int au_mvd_args_parent(const unsigned char dmsg,
c2b27bf2
AM
25470+ struct au_mvd_args *a)
25471+{
25472+ int err;
25473+ aufs_bindex_t bindex;
25474+
25475+ err = 0;
25476+ if (unlikely(au_alive_dir(a->parent))) {
25477+ err = -ENOENT;
392086de 25478+ AU_MVD_PR(dmsg, "parent dir is dead\n");
c2b27bf2
AM
25479+ goto out;
25480+ }
25481+
25482+ a->bopq = au_dbdiropq(a->parent);
25483+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
25484+ AuDbg("b%d\n", bindex);
25485+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
25486+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
25487+ err = -EINVAL;
392086de
AM
25488+ a->mvd_errno = EAU_MVDOWN_OPAQUE;
25489+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n",
c2b27bf2
AM
25490+ a->bopq, a->mvd_bdst);
25491+ }
25492+
25493+out:
25494+ AuTraceErr(err);
25495+ return err;
25496+}
25497+
392086de 25498+static int au_mvd_args_intermediate(const unsigned char dmsg,
c2b27bf2
AM
25499+ struct au_mvd_args *a)
25500+{
25501+ int err;
25502+ struct au_dinfo *dinfo, *tmp;
25503+
25504+ /* lookup the next lower positive entry */
25505+ err = -ENOMEM;
25506+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP);
25507+ if (unlikely(!tmp))
25508+ goto out;
25509+
25510+ a->bfound = -1;
25511+ a->bwh = -1;
25512+ dinfo = au_di(a->dentry);
25513+ au_di_cp(tmp, dinfo);
25514+ au_di_swap(tmp, dinfo);
25515+
25516+ /* returns the number of positive dentries */
5afbbe0d
AM
25517+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1,
25518+ /* AuLkup_IGNORE_PERM */ 0);
c2b27bf2
AM
25519+ if (!err)
25520+ a->bwh = au_dbwh(a->dentry);
25521+ else if (err > 0)
5afbbe0d 25522+ a->bfound = au_dbtop(a->dentry);
c2b27bf2
AM
25523+
25524+ au_di_swap(tmp, dinfo);
25525+ au_rw_write_unlock(&tmp->di_rwsem);
25526+ au_di_free(tmp);
25527+ if (unlikely(err < 0))
392086de 25528+ AU_MVD_PR(dmsg, "failed look-up lower\n");
c2b27bf2
AM
25529+
25530+ /*
25531+ * here, we have these cases.
25532+ * bfound == -1
25533+ * no positive dentry under bsrc. there are more sub-cases.
25534+ * bwh < 0
25535+ * there no whiteout, we can safely move-down.
25536+ * bwh <= bsrc
25537+ * impossible
25538+ * bsrc < bwh && bwh < bdst
25539+ * there is a whiteout on RO branch. cannot proceed.
25540+ * bwh == bdst
25541+ * there is a whiteout on the RW target branch. it should
25542+ * be removed.
25543+ * bdst < bwh
25544+ * there is a whiteout somewhere unrelated branch.
25545+ * -1 < bfound && bfound <= bsrc
25546+ * impossible.
25547+ * bfound < bdst
25548+ * found, but it is on RO branch between bsrc and bdst. cannot
25549+ * proceed.
25550+ * bfound == bdst
25551+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return
25552+ * error.
25553+ * bdst < bfound
25554+ * found, after we create the file on bdst, it will be hidden.
25555+ */
25556+
25557+ AuDebugOn(a->bfound == -1
25558+ && a->bwh != -1
25559+ && a->bwh <= a->mvd_bsrc);
25560+ AuDebugOn(-1 < a->bfound
25561+ && a->bfound <= a->mvd_bsrc);
25562+
25563+ err = -EINVAL;
25564+ if (a->bfound == -1
25565+ && a->mvd_bsrc < a->bwh
25566+ && a->bwh != -1
25567+ && a->bwh < a->mvd_bdst) {
392086de
AM
25568+ a->mvd_errno = EAU_MVDOWN_WHITEOUT;
25569+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n",
c2b27bf2
AM
25570+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh);
25571+ goto out;
25572+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) {
392086de
AM
25573+ a->mvd_errno = EAU_MVDOWN_UPPER;
25574+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n",
c2b27bf2
AM
25575+ a->mvd_bdst, a->bfound);
25576+ goto out;
25577+ }
25578+
25579+ err = 0; /* success */
25580+
25581+out:
25582+ AuTraceErr(err);
25583+ return err;
25584+}
25585+
392086de 25586+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25587+{
25588+ int err;
25589+
392086de
AM
25590+ err = 0;
25591+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25592+ && a->bfound == a->mvd_bdst)
25593+ err = -EEXIST;
c2b27bf2
AM
25594+ AuTraceErr(err);
25595+ return err;
25596+}
25597+
392086de 25598+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25599+{
25600+ int err;
25601+ struct au_branch *br;
25602+
25603+ err = -EISDIR;
25604+ if (unlikely(S_ISDIR(a->inode->i_mode)))
25605+ goto out;
25606+
25607+ err = -EINVAL;
392086de 25608+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER))
5afbbe0d 25609+ a->mvd_bsrc = au_ibtop(a->inode);
392086de
AM
25610+ else {
25611+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid);
25612+ if (unlikely(a->mvd_bsrc < 0
5afbbe0d
AM
25613+ || (a->mvd_bsrc < au_dbtop(a->dentry)
25614+ || au_dbbot(a->dentry) < a->mvd_bsrc
392086de 25615+ || !au_h_dptr(a->dentry, a->mvd_bsrc))
5afbbe0d
AM
25616+ || (a->mvd_bsrc < au_ibtop(a->inode)
25617+ || au_ibbot(a->inode) < a->mvd_bsrc
392086de
AM
25618+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) {
25619+ a->mvd_errno = EAU_MVDOWN_NOUPPER;
25620+ AU_MVD_PR(dmsg, "no upper\n");
25621+ goto out;
25622+ }
25623+ }
5afbbe0d 25624+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) {
392086de
AM
25625+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25626+ AU_MVD_PR(dmsg, "on the bottom\n");
c2b27bf2
AM
25627+ goto out;
25628+ }
392086de 25629+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
c2b27bf2
AM
25630+ br = au_sbr(a->sb, a->mvd_bsrc);
25631+ err = au_br_rdonly(br);
392086de
AM
25632+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) {
25633+ if (unlikely(err))
25634+ goto out;
25635+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode)
25636+ || IS_APPEND(a->mvd_h_src_inode))) {
25637+ if (err)
25638+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R;
25639+ /* go on */
25640+ } else
c2b27bf2
AM
25641+ goto out;
25642+
25643+ err = -EINVAL;
392086de
AM
25644+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) {
25645+ a->mvd_bdst = find_lower_writable(a);
25646+ if (unlikely(a->mvd_bdst < 0)) {
25647+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25648+ AU_MVD_PR(dmsg, "no writable lower branch\n");
25649+ goto out;
25650+ }
25651+ } else {
25652+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid);
25653+ if (unlikely(a->mvd_bdst < 0
5afbbe0d 25654+ || au_sbbot(a->sb) < a->mvd_bdst)) {
392086de
AM
25655+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR;
25656+ AU_MVD_PR(dmsg, "no lower brid\n");
25657+ goto out;
25658+ }
c2b27bf2
AM
25659+ }
25660+
392086de 25661+ err = au_mvd_args_busy(dmsg, a);
c2b27bf2 25662+ if (!err)
392086de 25663+ err = au_mvd_args_parent(dmsg, a);
c2b27bf2 25664+ if (!err)
392086de 25665+ err = au_mvd_args_intermediate(dmsg, a);
c2b27bf2 25666+ if (!err)
392086de 25667+ err = au_mvd_args_exist(dmsg, a);
c2b27bf2
AM
25668+ if (!err)
25669+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);
25670+
25671+out:
25672+ AuTraceErr(err);
25673+ return err;
25674+}
25675+
25676+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg)
25677+{
392086de
AM
25678+ int err, e;
25679+ unsigned char dmsg;
25680+ struct au_mvd_args *args;
79b8bda9 25681+ struct inode *inode;
c2b27bf2 25682+
79b8bda9 25683+ inode = d_inode(dentry);
c2b27bf2
AM
25684+ err = -EPERM;
25685+ if (unlikely(!capable(CAP_SYS_ADMIN)))
25686+ goto out;
25687+
392086de
AM
25688+ err = -ENOMEM;
25689+ args = kmalloc(sizeof(*args), GFP_NOFS);
25690+ if (unlikely(!args))
25691+ goto out;
25692+
25693+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown));
25694+ if (!err)
ba1aed25
AM
25695+ /* VERIFY_WRITE */
25696+ err = !access_ok(uarg, sizeof(*uarg));
c2b27bf2
AM
25697+ if (unlikely(err)) {
25698+ err = -EFAULT;
392086de
AM
25699+ AuTraceErr(err);
25700+ goto out_free;
c2b27bf2 25701+ }
392086de
AM
25702+ AuDbg("flags 0x%x\n", args->mvdown.flags);
25703+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R);
25704+ args->mvdown.au_errno = 0;
25705+ args->dentry = dentry;
79b8bda9 25706+ args->inode = inode;
392086de 25707+ args->sb = dentry->d_sb;
c2b27bf2 25708+
392086de
AM
25709+ err = -ENOENT;
25710+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG);
25711+ args->parent = dget_parent(dentry);
5527c038 25712+ args->dir = d_inode(args->parent);
febd17d6 25713+ inode_lock_nested(args->dir, I_MUTEX_PARENT);
392086de
AM
25714+ dput(args->parent);
25715+ if (unlikely(args->parent != dentry->d_parent)) {
25716+ AU_MVD_PR(dmsg, "parent dir is moved\n");
c2b27bf2
AM
25717+ goto out_dir;
25718+ }
25719+
febd17d6 25720+ inode_lock_nested(inode, I_MUTEX_CHILD);
b95c5147 25721+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW);
c2b27bf2
AM
25722+ if (unlikely(err))
25723+ goto out_inode;
25724+
392086de
AM
25725+ di_write_lock_parent(args->parent);
25726+ err = au_mvd_args(dmsg, args);
c2b27bf2
AM
25727+ if (unlikely(err))
25728+ goto out_parent;
25729+
392086de 25730+ err = au_do_mvdown(dmsg, args);
c2b27bf2
AM
25731+ if (unlikely(err))
25732+ goto out_parent;
c2b27bf2 25733+
392086de 25734+ au_cpup_attr_timesizes(args->dir);
79b8bda9
AM
25735+ au_cpup_attr_timesizes(inode);
25736+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER))
25737+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst));
c2b27bf2
AM
25738+ /* au_digen_dec(dentry); */
25739+
25740+out_parent:
392086de 25741+ di_write_unlock(args->parent);
c2b27bf2
AM
25742+ aufs_read_unlock(dentry, AuLock_DW);
25743+out_inode:
febd17d6 25744+ inode_unlock(inode);
c2b27bf2 25745+out_dir:
febd17d6 25746+ inode_unlock(args->dir);
392086de
AM
25747+out_free:
25748+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown));
25749+ if (unlikely(e))
25750+ err = -EFAULT;
9f237c51 25751+ au_kfree_rcu(args);
c2b27bf2
AM
25752+out:
25753+ AuTraceErr(err);
25754+ return err;
25755+}
25756diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
fbc438ed
JR
25757--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 08:00:00.000000000 +0800
25758+++ linux/fs/aufs/opts.c 2019-07-11 21:21:54.382384486 +0800
acd2b654 25759@@ -0,0 +1,1877 @@
cd7a4cd9 25760+// SPDX-License-Identifier: GPL-2.0
1facf9fc 25761+/*
ba1aed25 25762+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 25763+ *
25764+ * This program, aufs is free software; you can redistribute it and/or modify
25765+ * it under the terms of the GNU General Public License as published by
25766+ * the Free Software Foundation; either version 2 of the License, or
25767+ * (at your option) any later version.
dece6358
AM
25768+ *
25769+ * This program is distributed in the hope that it will be useful,
25770+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25771+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25772+ * GNU General Public License for more details.
25773+ *
25774+ * You should have received a copy of the GNU General Public License
523b37e3 25775+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 25776+ */
25777+
25778+/*
25779+ * mount options/flags
25780+ */
25781+
dece6358 25782+#include <linux/namei.h>
1facf9fc 25783+#include <linux/types.h> /* a distribution requires */
25784+#include <linux/parser.h>
25785+#include "aufs.h"
25786+
25787+/* ---------------------------------------------------------------------- */
25788+
25789+enum {
25790+ Opt_br,
7e9cd9fe
AM
25791+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
25792+ Opt_idel, Opt_imod,
25793+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
dece6358 25794+ Opt_rdblk_def, Opt_rdhash_def,
7e9cd9fe 25795+ Opt_xino, Opt_noxino,
1facf9fc 25796+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
25797+ Opt_trunc_xino_path, Opt_itrunc_xino,
25798+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 25799+ Opt_shwh, Opt_noshwh,
1facf9fc 25800+ Opt_plink, Opt_noplink, Opt_list_plink,
25801+ Opt_udba,
4a4d8108 25802+ Opt_dio, Opt_nodio,
1facf9fc 25803+ Opt_diropq_a, Opt_diropq_w,
25804+ Opt_warn_perm, Opt_nowarn_perm,
25805+ Opt_wbr_copyup, Opt_wbr_create,
076b876e 25806+ Opt_fhsm_sec,
1facf9fc 25807+ Opt_verbose, Opt_noverbose,
25808+ Opt_sum, Opt_nosum, Opt_wsum,
076b876e 25809+ Opt_dirperm1, Opt_nodirperm1,
8b6a4947 25810+ Opt_dirren, Opt_nodirren,
c1595e42 25811+ Opt_acl, Opt_noacl,
1facf9fc 25812+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
25813+};
25814+
25815+static match_table_t options = {
25816+ {Opt_br, "br=%s"},
25817+ {Opt_br, "br:%s"},
25818+
25819+ {Opt_add, "add=%d:%s"},
25820+ {Opt_add, "add:%d:%s"},
25821+ {Opt_add, "ins=%d:%s"},
25822+ {Opt_add, "ins:%d:%s"},
25823+ {Opt_append, "append=%s"},
25824+ {Opt_append, "append:%s"},
25825+ {Opt_prepend, "prepend=%s"},
25826+ {Opt_prepend, "prepend:%s"},
25827+
25828+ {Opt_del, "del=%s"},
25829+ {Opt_del, "del:%s"},
25830+ /* {Opt_idel, "idel:%d"}, */
25831+ {Opt_mod, "mod=%s"},
25832+ {Opt_mod, "mod:%s"},
25833+ /* {Opt_imod, "imod:%d:%s"}, */
25834+
25835+ {Opt_dirwh, "dirwh=%d"},
25836+
25837+ {Opt_xino, "xino=%s"},
25838+ {Opt_noxino, "noxino"},
25839+ {Opt_trunc_xino, "trunc_xino"},
25840+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
25841+ {Opt_notrunc_xino, "notrunc_xino"},
25842+ {Opt_trunc_xino_path, "trunc_xino=%s"},
25843+ {Opt_itrunc_xino, "itrunc_xino=%d"},
25844+ /* {Opt_zxino, "zxino=%s"}, */
25845+ {Opt_trunc_xib, "trunc_xib"},
25846+ {Opt_notrunc_xib, "notrunc_xib"},
25847+
e49829fe 25848+#ifdef CONFIG_PROC_FS
1facf9fc 25849+ {Opt_plink, "plink"},
e49829fe
JR
25850+#else
25851+ {Opt_ignore_silent, "plink"},
25852+#endif
25853+
1facf9fc 25854+ {Opt_noplink, "noplink"},
e49829fe 25855+
1facf9fc 25856+#ifdef CONFIG_AUFS_DEBUG
25857+ {Opt_list_plink, "list_plink"},
25858+#endif
25859+
25860+ {Opt_udba, "udba=%s"},
25861+
4a4d8108
AM
25862+ {Opt_dio, "dio"},
25863+ {Opt_nodio, "nodio"},
25864+
8b6a4947
AM
25865+#ifdef CONFIG_AUFS_DIRREN
25866+ {Opt_dirren, "dirren"},
25867+ {Opt_nodirren, "nodirren"},
25868+#else
25869+ {Opt_ignore, "dirren"},
25870+ {Opt_ignore_silent, "nodirren"},
25871+#endif
25872+
076b876e
AM
25873+#ifdef CONFIG_AUFS_FHSM
25874+ {Opt_fhsm_sec, "fhsm_sec=%d"},
25875+#else
8b6a4947 25876+ {Opt_ignore, "fhsm_sec=%d"},
076b876e
AM
25877+#endif
25878+
1facf9fc 25879+ {Opt_diropq_a, "diropq=always"},
25880+ {Opt_diropq_a, "diropq=a"},
25881+ {Opt_diropq_w, "diropq=whiteouted"},
25882+ {Opt_diropq_w, "diropq=w"},
25883+
25884+ {Opt_warn_perm, "warn_perm"},
25885+ {Opt_nowarn_perm, "nowarn_perm"},
25886+
25887+ /* keep them temporary */
1facf9fc 25888+ {Opt_ignore_silent, "nodlgt"},
8b6a4947 25889+ {Opt_ignore, "clean_plink"},
1facf9fc 25890+
dece6358
AM
25891+#ifdef CONFIG_AUFS_SHWH
25892+ {Opt_shwh, "shwh"},
25893+#endif
25894+ {Opt_noshwh, "noshwh"},
25895+
076b876e
AM
25896+ {Opt_dirperm1, "dirperm1"},
25897+ {Opt_nodirperm1, "nodirperm1"},
25898+
1facf9fc 25899+ {Opt_verbose, "verbose"},
25900+ {Opt_verbose, "v"},
25901+ {Opt_noverbose, "noverbose"},
25902+ {Opt_noverbose, "quiet"},
25903+ {Opt_noverbose, "q"},
25904+ {Opt_noverbose, "silent"},
25905+
25906+ {Opt_sum, "sum"},
25907+ {Opt_nosum, "nosum"},
25908+ {Opt_wsum, "wsum"},
25909+
25910+ {Opt_rdcache, "rdcache=%d"},
25911+ {Opt_rdblk, "rdblk=%d"},
dece6358 25912+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 25913+ {Opt_rdhash, "rdhash=%d"},
dece6358 25914+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 25915+
25916+ {Opt_wbr_create, "create=%s"},
25917+ {Opt_wbr_create, "create_policy=%s"},
25918+ {Opt_wbr_copyup, "cpup=%s"},
25919+ {Opt_wbr_copyup, "copyup=%s"},
25920+ {Opt_wbr_copyup, "copyup_policy=%s"},
25921+
c1595e42
JR
25922+ /* generic VFS flag */
25923+#ifdef CONFIG_FS_POSIX_ACL
25924+ {Opt_acl, "acl"},
25925+ {Opt_noacl, "noacl"},
25926+#else
8b6a4947 25927+ {Opt_ignore, "acl"},
c1595e42
JR
25928+ {Opt_ignore_silent, "noacl"},
25929+#endif
25930+
1facf9fc 25931+ /* internal use for the scripts */
25932+ {Opt_ignore_silent, "si=%s"},
25933+
25934+ {Opt_br, "dirs=%s"},
25935+ {Opt_ignore, "debug=%d"},
25936+ {Opt_ignore, "delete=whiteout"},
25937+ {Opt_ignore, "delete=all"},
25938+ {Opt_ignore, "imap=%s"},
25939+
1308ab2a 25940+ /* temporary workaround, due to old mount(8)? */
25941+ {Opt_ignore_silent, "relatime"},
25942+
1facf9fc 25943+ {Opt_err, NULL}
25944+};
25945+
25946+/* ---------------------------------------------------------------------- */
25947+
076b876e 25948+static const char *au_parser_pattern(int val, match_table_t tbl)
1facf9fc 25949+{
076b876e
AM
25950+ struct match_token *p;
25951+
25952+ p = tbl;
25953+ while (p->pattern) {
25954+ if (p->token == val)
25955+ return p->pattern;
25956+ p++;
1facf9fc 25957+ }
25958+ BUG();
25959+ return "??";
25960+}
25961+
076b876e
AM
25962+static const char *au_optstr(int *val, match_table_t tbl)
25963+{
25964+ struct match_token *p;
25965+ int v;
25966+
25967+ v = *val;
2000de60
JR
25968+ if (!v)
25969+ goto out;
076b876e 25970+ p = tbl;
2000de60
JR
25971+ while (p->pattern) {
25972+ if (p->token
25973+ && (v & p->token) == p->token) {
076b876e
AM
25974+ *val &= ~p->token;
25975+ return p->pattern;
25976+ }
25977+ p++;
25978+ }
2000de60
JR
25979+
25980+out:
076b876e
AM
25981+ return NULL;
25982+}
25983+
1facf9fc 25984+/* ---------------------------------------------------------------------- */
25985+
1e00d052 25986+static match_table_t brperm = {
1facf9fc 25987+ {AuBrPerm_RO, AUFS_BRPERM_RO},
25988+ {AuBrPerm_RR, AUFS_BRPERM_RR},
25989+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
25990+ {0, NULL}
25991+};
1facf9fc 25992+
86dc4139 25993+static match_table_t brattr = {
076b876e
AM
25994+ /* general */
25995+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG},
25996+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL},
c1595e42 25997+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */
86dc4139 25998+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
2000de60 25999+#ifdef CONFIG_AUFS_FHSM
076b876e 26000+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM},
2000de60
JR
26001+#endif
26002+#ifdef CONFIG_AUFS_XATTR
c1595e42
JR
26003+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX},
26004+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC},
26005+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS},
26006+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR},
26007+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR},
26008+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH},
2000de60 26009+#endif
076b876e
AM
26010+
26011+ /* ro/rr branch */
1e00d052 26012+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
076b876e
AM
26013+
26014+ /* rw branch */
26015+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO},
1e00d052 26016+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
076b876e 26017+
1e00d052 26018+ {0, NULL}
1facf9fc 26019+};
26020+
1e00d052
AM
26021+static int br_attr_val(char *str, match_table_t table, substring_t args[])
26022+{
26023+ int attr, v;
26024+ char *p;
26025+
26026+ attr = 0;
26027+ do {
26028+ p = strchr(str, '+');
26029+ if (p)
26030+ *p = 0;
26031+ v = match_token(str, table, args);
076b876e
AM
26032+ if (v) {
26033+ if (v & AuBrAttr_CMOO_Mask)
26034+ attr &= ~AuBrAttr_CMOO_Mask;
1e00d052 26035+ attr |= v;
076b876e 26036+ } else {
1e00d052
AM
26037+ if (p)
26038+ *p = '+';
0c3ec466 26039+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
26040+ break;
26041+ }
26042+ if (p)
26043+ str = p + 1;
26044+ } while (p);
26045+
26046+ return attr;
26047+}
26048+
076b876e
AM
26049+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm)
26050+{
26051+ int sz;
26052+ const char *p;
26053+ char *q;
26054+
076b876e
AM
26055+ q = str->a;
26056+ *q = 0;
26057+ p = au_optstr(&perm, brattr);
26058+ if (p) {
26059+ sz = strlen(p);
26060+ memcpy(q, p, sz + 1);
26061+ q += sz;
26062+ } else
26063+ goto out;
26064+
26065+ do {
26066+ p = au_optstr(&perm, brattr);
26067+ if (p) {
26068+ *q++ = '+';
26069+ sz = strlen(p);
26070+ memcpy(q, p, sz + 1);
26071+ q += sz;
26072+ }
26073+ } while (p);
26074+
26075+out:
c1595e42 26076+ return q - str->a;
076b876e
AM
26077+}
26078+
4a4d8108 26079+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 26080+{
076b876e
AM
26081+ int val, bad, sz;
26082+ char *p;
1facf9fc 26083+ substring_t args[MAX_OPT_ARGS];
076b876e 26084+ au_br_perm_str_t attr;
1facf9fc 26085+
1e00d052
AM
26086+ p = strchr(perm, '+');
26087+ if (p)
26088+ *p = 0;
26089+ val = match_token(perm, brperm, args);
26090+ if (!val) {
26091+ if (p)
26092+ *p = '+';
0c3ec466 26093+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
26094+ val = AuBrPerm_RO;
26095+ goto out;
26096+ }
26097+ if (!p)
26098+ goto out;
26099+
076b876e
AM
26100+ val |= br_attr_val(p + 1, brattr, args);
26101+
26102+ bad = 0;
86dc4139 26103+ switch (val & AuBrPerm_Mask) {
1e00d052
AM
26104+ case AuBrPerm_RO:
26105+ case AuBrPerm_RR:
076b876e
AM
26106+ bad = val & AuBrWAttr_Mask;
26107+ val &= ~AuBrWAttr_Mask;
1e00d052
AM
26108+ break;
26109+ case AuBrPerm_RW:
076b876e
AM
26110+ bad = val & AuBrRAttr_Mask;
26111+ val &= ~AuBrRAttr_Mask;
1e00d052
AM
26112+ break;
26113+ }
c1595e42
JR
26114+
26115+ /*
26116+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs
26117+ * does not treat it as an error, just warning.
26118+ * this is a tiny guard for the user operation.
26119+ */
26120+ if (val & AuBrAttr_UNPIN) {
26121+ bad |= AuBrAttr_UNPIN;
26122+ val &= ~AuBrAttr_UNPIN;
26123+ }
26124+
076b876e
AM
26125+ if (unlikely(bad)) {
26126+ sz = au_do_optstr_br_attr(&attr, bad);
26127+ AuDebugOn(!sz);
26128+ pr_warn("ignored branch attribute %s\n", attr.a);
26129+ }
1e00d052
AM
26130+
26131+out:
1facf9fc 26132+ return val;
26133+}
26134+
076b876e 26135+void au_optstr_br_perm(au_br_perm_str_t *str, int perm)
1facf9fc 26136+{
076b876e
AM
26137+ au_br_perm_str_t attr;
26138+ const char *p;
26139+ char *q;
1e00d052
AM
26140+ int sz;
26141+
076b876e
AM
26142+ q = str->a;
26143+ p = au_optstr(&perm, brperm);
26144+ AuDebugOn(!p || !*p);
26145+ sz = strlen(p);
26146+ memcpy(q, p, sz + 1);
26147+ q += sz;
1e00d052 26148+
076b876e
AM
26149+ sz = au_do_optstr_br_attr(&attr, perm);
26150+ if (sz) {
26151+ *q++ = '+';
26152+ memcpy(q, attr.a, sz + 1);
1e00d052
AM
26153+ }
26154+
076b876e 26155+ AuDebugOn(strlen(str->a) >= sizeof(str->a));
1facf9fc 26156+}
26157+
26158+/* ---------------------------------------------------------------------- */
26159+
26160+static match_table_t udbalevel = {
26161+ {AuOpt_UDBA_REVAL, "reval"},
26162+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
26163+#ifdef CONFIG_AUFS_HNOTIFY
26164+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
26165+#ifdef CONFIG_AUFS_HFSNOTIFY
26166+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 26167+#endif
1facf9fc 26168+#endif
26169+ {-1, NULL}
26170+};
26171+
4a4d8108 26172+static int noinline_for_stack udba_val(char *str)
1facf9fc 26173+{
26174+ substring_t args[MAX_OPT_ARGS];
26175+
7f207e10 26176+ return match_token(str, udbalevel, args);
1facf9fc 26177+}
26178+
26179+const char *au_optstr_udba(int udba)
26180+{
076b876e 26181+ return au_parser_pattern(udba, udbalevel);
1facf9fc 26182+}
26183+
26184+/* ---------------------------------------------------------------------- */
26185+
26186+static match_table_t au_wbr_create_policy = {
26187+ {AuWbrCreate_TDP, "tdp"},
26188+ {AuWbrCreate_TDP, "top-down-parent"},
26189+ {AuWbrCreate_RR, "rr"},
26190+ {AuWbrCreate_RR, "round-robin"},
26191+ {AuWbrCreate_MFS, "mfs"},
26192+ {AuWbrCreate_MFS, "most-free-space"},
26193+ {AuWbrCreate_MFSV, "mfs:%d"},
26194+ {AuWbrCreate_MFSV, "most-free-space:%d"},
26195+
f2c43d5f
AM
26196+ /* top-down regardless the parent, and then mfs */
26197+ {AuWbrCreate_TDMFS, "tdmfs:%d"},
26198+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"},
26199+
1facf9fc 26200+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
26201+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
26202+ {AuWbrCreate_PMFS, "pmfs"},
26203+ {AuWbrCreate_PMFSV, "pmfs:%d"},
392086de
AM
26204+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"},
26205+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"},
1facf9fc 26206+
26207+ {-1, NULL}
26208+};
26209+
1facf9fc 26210+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
26211+ struct au_opt_wbr_create *create)
26212+{
26213+ int err;
26214+ unsigned long long ull;
26215+
26216+ err = 0;
a2654f78 26217+ if (!match_u64(arg, &ull))
1facf9fc 26218+ create->mfsrr_watermark = ull;
26219+ else {
4a4d8108 26220+ pr_err("bad integer in %s\n", str);
1facf9fc 26221+ err = -EINVAL;
26222+ }
26223+
26224+ return err;
26225+}
26226+
26227+static int au_wbr_mfs_sec(substring_t *arg, char *str,
26228+ struct au_opt_wbr_create *create)
26229+{
26230+ int n, err;
26231+
26232+ err = 0;
027c5e7a 26233+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 26234+ create->mfs_second = n;
26235+ else {
4a4d8108 26236+ pr_err("bad integer in %s\n", str);
1facf9fc 26237+ err = -EINVAL;
26238+ }
26239+
26240+ return err;
26241+}
26242+
4a4d8108
AM
26243+static int noinline_for_stack
26244+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 26245+{
26246+ int err, e;
26247+ substring_t args[MAX_OPT_ARGS];
26248+
26249+ err = match_token(str, au_wbr_create_policy, args);
26250+ create->wbr_create = err;
26251+ switch (err) {
26252+ case AuWbrCreate_MFSRRV:
f2c43d5f 26253+ case AuWbrCreate_TDMFSV:
392086de 26254+ case AuWbrCreate_PMFSRRV:
1facf9fc 26255+ e = au_wbr_mfs_wmark(&args[0], str, create);
26256+ if (!e)
26257+ e = au_wbr_mfs_sec(&args[1], str, create);
26258+ if (unlikely(e))
26259+ err = e;
26260+ break;
26261+ case AuWbrCreate_MFSRR:
f2c43d5f 26262+ case AuWbrCreate_TDMFS:
392086de 26263+ case AuWbrCreate_PMFSRR:
1facf9fc 26264+ e = au_wbr_mfs_wmark(&args[0], str, create);
26265+ if (unlikely(e)) {
26266+ err = e;
26267+ break;
26268+ }
26269+ /*FALLTHROUGH*/
26270+ case AuWbrCreate_MFS:
26271+ case AuWbrCreate_PMFS:
027c5e7a 26272+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 26273+ break;
26274+ case AuWbrCreate_MFSV:
26275+ case AuWbrCreate_PMFSV:
26276+ e = au_wbr_mfs_sec(&args[0], str, create);
26277+ if (unlikely(e))
26278+ err = e;
26279+ break;
26280+ }
26281+
26282+ return err;
26283+}
26284+
26285+const char *au_optstr_wbr_create(int wbr_create)
26286+{
076b876e 26287+ return au_parser_pattern(wbr_create, au_wbr_create_policy);
1facf9fc 26288+}
26289+
26290+static match_table_t au_wbr_copyup_policy = {
26291+ {AuWbrCopyup_TDP, "tdp"},
26292+ {AuWbrCopyup_TDP, "top-down-parent"},
26293+ {AuWbrCopyup_BUP, "bup"},
26294+ {AuWbrCopyup_BUP, "bottom-up-parent"},
26295+ {AuWbrCopyup_BU, "bu"},
26296+ {AuWbrCopyup_BU, "bottom-up"},
26297+ {-1, NULL}
26298+};
26299+
4a4d8108 26300+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 26301+{
26302+ substring_t args[MAX_OPT_ARGS];
26303+
26304+ return match_token(str, au_wbr_copyup_policy, args);
26305+}
26306+
26307+const char *au_optstr_wbr_copyup(int wbr_copyup)
26308+{
076b876e 26309+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy);
1facf9fc 26310+}
26311+
26312+/* ---------------------------------------------------------------------- */
26313+
26314+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
26315+
26316+static void dump_opts(struct au_opts *opts)
26317+{
26318+#ifdef CONFIG_AUFS_DEBUG
26319+ /* reduce stack space */
26320+ union {
26321+ struct au_opt_add *add;
26322+ struct au_opt_del *del;
26323+ struct au_opt_mod *mod;
26324+ struct au_opt_xino *xino;
26325+ struct au_opt_xino_itrunc *xino_itrunc;
26326+ struct au_opt_wbr_create *create;
26327+ } u;
26328+ struct au_opt *opt;
26329+
26330+ opt = opts->opt;
26331+ while (opt->type != Opt_tail) {
26332+ switch (opt->type) {
26333+ case Opt_add:
26334+ u.add = &opt->add;
26335+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
26336+ u.add->bindex, u.add->pathname, u.add->perm,
26337+ u.add->path.dentry);
26338+ break;
26339+ case Opt_del:
26340+ case Opt_idel:
26341+ u.del = &opt->del;
26342+ AuDbg("del {%s, %p}\n",
26343+ u.del->pathname, u.del->h_path.dentry);
26344+ break;
26345+ case Opt_mod:
26346+ case Opt_imod:
26347+ u.mod = &opt->mod;
26348+ AuDbg("mod {%s, 0x%x, %p}\n",
26349+ u.mod->path, u.mod->perm, u.mod->h_root);
26350+ break;
26351+ case Opt_append:
26352+ u.add = &opt->add;
26353+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
26354+ u.add->bindex, u.add->pathname, u.add->perm,
26355+ u.add->path.dentry);
26356+ break;
26357+ case Opt_prepend:
26358+ u.add = &opt->add;
26359+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
26360+ u.add->bindex, u.add->pathname, u.add->perm,
26361+ u.add->path.dentry);
26362+ break;
26363+ case Opt_dirwh:
26364+ AuDbg("dirwh %d\n", opt->dirwh);
26365+ break;
26366+ case Opt_rdcache:
26367+ AuDbg("rdcache %d\n", opt->rdcache);
26368+ break;
26369+ case Opt_rdblk:
26370+ AuDbg("rdblk %u\n", opt->rdblk);
26371+ break;
dece6358
AM
26372+ case Opt_rdblk_def:
26373+ AuDbg("rdblk_def\n");
26374+ break;
1facf9fc 26375+ case Opt_rdhash:
26376+ AuDbg("rdhash %u\n", opt->rdhash);
26377+ break;
dece6358
AM
26378+ case Opt_rdhash_def:
26379+ AuDbg("rdhash_def\n");
26380+ break;
1facf9fc 26381+ case Opt_xino:
26382+ u.xino = &opt->xino;
523b37e3 26383+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
1facf9fc 26384+ break;
26385+ case Opt_trunc_xino:
26386+ AuLabel(trunc_xino);
26387+ break;
26388+ case Opt_notrunc_xino:
26389+ AuLabel(notrunc_xino);
26390+ break;
26391+ case Opt_trunc_xino_path:
26392+ case Opt_itrunc_xino:
26393+ u.xino_itrunc = &opt->xino_itrunc;
26394+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
26395+ break;
1facf9fc 26396+ case Opt_noxino:
26397+ AuLabel(noxino);
26398+ break;
26399+ case Opt_trunc_xib:
26400+ AuLabel(trunc_xib);
26401+ break;
26402+ case Opt_notrunc_xib:
26403+ AuLabel(notrunc_xib);
26404+ break;
dece6358
AM
26405+ case Opt_shwh:
26406+ AuLabel(shwh);
26407+ break;
26408+ case Opt_noshwh:
26409+ AuLabel(noshwh);
26410+ break;
076b876e
AM
26411+ case Opt_dirperm1:
26412+ AuLabel(dirperm1);
26413+ break;
26414+ case Opt_nodirperm1:
26415+ AuLabel(nodirperm1);
26416+ break;
1facf9fc 26417+ case Opt_plink:
26418+ AuLabel(plink);
26419+ break;
26420+ case Opt_noplink:
26421+ AuLabel(noplink);
26422+ break;
26423+ case Opt_list_plink:
26424+ AuLabel(list_plink);
26425+ break;
26426+ case Opt_udba:
26427+ AuDbg("udba %d, %s\n",
26428+ opt->udba, au_optstr_udba(opt->udba));
26429+ break;
4a4d8108
AM
26430+ case Opt_dio:
26431+ AuLabel(dio);
26432+ break;
26433+ case Opt_nodio:
26434+ AuLabel(nodio);
26435+ break;
1facf9fc 26436+ case Opt_diropq_a:
26437+ AuLabel(diropq_a);
26438+ break;
26439+ case Opt_diropq_w:
26440+ AuLabel(diropq_w);
26441+ break;
26442+ case Opt_warn_perm:
26443+ AuLabel(warn_perm);
26444+ break;
26445+ case Opt_nowarn_perm:
26446+ AuLabel(nowarn_perm);
26447+ break;
1facf9fc 26448+ case Opt_verbose:
26449+ AuLabel(verbose);
26450+ break;
26451+ case Opt_noverbose:
26452+ AuLabel(noverbose);
26453+ break;
26454+ case Opt_sum:
26455+ AuLabel(sum);
26456+ break;
26457+ case Opt_nosum:
26458+ AuLabel(nosum);
26459+ break;
26460+ case Opt_wsum:
26461+ AuLabel(wsum);
26462+ break;
26463+ case Opt_wbr_create:
26464+ u.create = &opt->wbr_create;
26465+ AuDbg("create %d, %s\n", u.create->wbr_create,
26466+ au_optstr_wbr_create(u.create->wbr_create));
26467+ switch (u.create->wbr_create) {
26468+ case AuWbrCreate_MFSV:
26469+ case AuWbrCreate_PMFSV:
26470+ AuDbg("%d sec\n", u.create->mfs_second);
26471+ break;
26472+ case AuWbrCreate_MFSRR:
f2c43d5f 26473+ case AuWbrCreate_TDMFS:
1facf9fc 26474+ AuDbg("%llu watermark\n",
26475+ u.create->mfsrr_watermark);
26476+ break;
26477+ case AuWbrCreate_MFSRRV:
f2c43d5f 26478+ case AuWbrCreate_TDMFSV:
392086de 26479+ case AuWbrCreate_PMFSRRV:
1facf9fc 26480+ AuDbg("%llu watermark, %d sec\n",
26481+ u.create->mfsrr_watermark,
26482+ u.create->mfs_second);
26483+ break;
26484+ }
26485+ break;
26486+ case Opt_wbr_copyup:
26487+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
26488+ au_optstr_wbr_copyup(opt->wbr_copyup));
26489+ break;
076b876e
AM
26490+ case Opt_fhsm_sec:
26491+ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
26492+ break;
8b6a4947
AM
26493+ case Opt_dirren:
26494+ AuLabel(dirren);
26495+ break;
26496+ case Opt_nodirren:
26497+ AuLabel(nodirren);
26498+ break;
c1595e42
JR
26499+ case Opt_acl:
26500+ AuLabel(acl);
26501+ break;
26502+ case Opt_noacl:
26503+ AuLabel(noacl);
26504+ break;
1facf9fc 26505+ default:
26506+ BUG();
26507+ }
26508+ opt++;
26509+ }
26510+#endif
26511+}
26512+
26513+void au_opts_free(struct au_opts *opts)
26514+{
26515+ struct au_opt *opt;
26516+
26517+ opt = opts->opt;
26518+ while (opt->type != Opt_tail) {
26519+ switch (opt->type) {
26520+ case Opt_add:
26521+ case Opt_append:
26522+ case Opt_prepend:
26523+ path_put(&opt->add.path);
26524+ break;
26525+ case Opt_del:
26526+ case Opt_idel:
26527+ path_put(&opt->del.h_path);
26528+ break;
26529+ case Opt_mod:
26530+ case Opt_imod:
26531+ dput(opt->mod.h_root);
26532+ break;
26533+ case Opt_xino:
26534+ fput(opt->xino.file);
26535+ break;
26536+ }
26537+ opt++;
26538+ }
26539+}
26540+
26541+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
26542+ aufs_bindex_t bindex)
26543+{
26544+ int err;
26545+ struct au_opt_add *add = &opt->add;
26546+ char *p;
26547+
26548+ add->bindex = bindex;
1e00d052 26549+ add->perm = AuBrPerm_RO;
1facf9fc 26550+ add->pathname = opt_str;
26551+ p = strchr(opt_str, '=');
26552+ if (p) {
26553+ *p++ = 0;
26554+ if (*p)
26555+ add->perm = br_perm_val(p);
26556+ }
26557+
26558+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
26559+ if (!err) {
26560+ if (!p) {
26561+ add->perm = AuBrPerm_RO;
26562+ if (au_test_fs_rr(add->path.dentry->d_sb))
26563+ add->perm = AuBrPerm_RR;
2121bcd9 26564+ else if (!bindex && !(sb_flags & SB_RDONLY))
1facf9fc 26565+ add->perm = AuBrPerm_RW;
26566+ }
26567+ opt->type = Opt_add;
26568+ goto out;
26569+ }
4a4d8108 26570+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 26571+ err = -EINVAL;
26572+
4f0767ce 26573+out:
1facf9fc 26574+ return err;
26575+}
26576+
26577+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
26578+{
26579+ int err;
26580+
26581+ del->pathname = args[0].from;
26582+ AuDbg("del path %s\n", del->pathname);
26583+
26584+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
26585+ if (unlikely(err))
4a4d8108 26586+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 26587+
26588+ return err;
26589+}
26590+
26591+#if 0 /* reserved for future use */
26592+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
26593+ struct au_opt_del *del, substring_t args[])
26594+{
26595+ int err;
26596+ struct dentry *root;
26597+
26598+ err = -EINVAL;
26599+ root = sb->s_root;
26600+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26601+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26602+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26603+ goto out;
26604+ }
26605+
26606+ err = 0;
26607+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
26608+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
26609+
4f0767ce 26610+out:
1facf9fc 26611+ aufs_read_unlock(root, !AuLock_IR);
26612+ return err;
26613+}
26614+#endif
26615+
4a4d8108
AM
26616+static int noinline_for_stack
26617+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 26618+{
26619+ int err;
26620+ struct path path;
26621+ char *p;
26622+
26623+ err = -EINVAL;
26624+ mod->path = args[0].from;
26625+ p = strchr(mod->path, '=');
26626+ if (unlikely(!p)) {
acd2b654 26627+ pr_err("no permission %s\n", args[0].from);
1facf9fc 26628+ goto out;
26629+ }
26630+
26631+ *p++ = 0;
26632+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
26633+ if (unlikely(err)) {
4a4d8108 26634+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 26635+ goto out;
26636+ }
26637+
26638+ mod->perm = br_perm_val(p);
26639+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
26640+ mod->h_root = dget(path.dentry);
26641+ path_put(&path);
26642+
4f0767ce 26643+out:
1facf9fc 26644+ return err;
26645+}
26646+
26647+#if 0 /* reserved for future use */
26648+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
26649+ struct au_opt_mod *mod, substring_t args[])
26650+{
26651+ int err;
26652+ struct dentry *root;
26653+
26654+ err = -EINVAL;
26655+ root = sb->s_root;
26656+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26657+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26658+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26659+ goto out;
26660+ }
26661+
26662+ err = 0;
26663+ mod->perm = br_perm_val(args[1].from);
26664+ AuDbg("mod path %s, perm 0x%x, %s\n",
26665+ mod->path, mod->perm, args[1].from);
26666+ mod->h_root = dget(au_h_dptr(root, bindex));
26667+
4f0767ce 26668+out:
1facf9fc 26669+ aufs_read_unlock(root, !AuLock_IR);
26670+ return err;
26671+}
26672+#endif
26673+
26674+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
26675+ substring_t args[])
26676+{
26677+ int err;
26678+ struct file *file;
26679+
83b672a5 26680+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0);
1facf9fc 26681+ err = PTR_ERR(file);
26682+ if (IS_ERR(file))
26683+ goto out;
26684+
26685+ err = -EINVAL;
2000de60 26686+ if (unlikely(file->f_path.dentry->d_sb == sb)) {
1facf9fc 26687+ fput(file);
4a4d8108 26688+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 26689+ goto out;
26690+ }
26691+
26692+ err = 0;
26693+ xino->file = file;
26694+ xino->path = args[0].from;
26695+
4f0767ce 26696+out:
1facf9fc 26697+ return err;
26698+}
26699+
4a4d8108
AM
26700+static int noinline_for_stack
26701+au_opts_parse_xino_itrunc_path(struct super_block *sb,
26702+ struct au_opt_xino_itrunc *xino_itrunc,
26703+ substring_t args[])
1facf9fc 26704+{
26705+ int err;
5afbbe0d 26706+ aufs_bindex_t bbot, bindex;
1facf9fc 26707+ struct path path;
26708+ struct dentry *root;
26709+
26710+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
26711+ if (unlikely(err)) {
4a4d8108 26712+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 26713+ goto out;
26714+ }
26715+
26716+ xino_itrunc->bindex = -1;
26717+ root = sb->s_root;
26718+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d
AM
26719+ bbot = au_sbbot(sb);
26720+ for (bindex = 0; bindex <= bbot; bindex++) {
1facf9fc 26721+ if (au_h_dptr(root, bindex) == path.dentry) {
26722+ xino_itrunc->bindex = bindex;
26723+ break;
26724+ }
26725+ }
26726+ aufs_read_unlock(root, !AuLock_IR);
26727+ path_put(&path);
26728+
26729+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 26730+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 26731+ err = -EINVAL;
26732+ }
26733+
4f0767ce 26734+out:
1facf9fc 26735+ return err;
26736+}
26737+
26738+/* called without aufs lock */
26739+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
26740+{
26741+ int err, n, token;
26742+ aufs_bindex_t bindex;
26743+ unsigned char skipped;
26744+ struct dentry *root;
26745+ struct au_opt *opt, *opt_tail;
26746+ char *opt_str;
26747+ /* reduce the stack space */
26748+ union {
26749+ struct au_opt_xino_itrunc *xino_itrunc;
26750+ struct au_opt_wbr_create *create;
26751+ } u;
26752+ struct {
26753+ substring_t args[MAX_OPT_ARGS];
26754+ } *a;
26755+
26756+ err = -ENOMEM;
26757+ a = kmalloc(sizeof(*a), GFP_NOFS);
26758+ if (unlikely(!a))
26759+ goto out;
26760+
26761+ root = sb->s_root;
26762+ err = 0;
26763+ bindex = 0;
26764+ opt = opts->opt;
26765+ opt_tail = opt + opts->max_opt - 1;
26766+ opt->type = Opt_tail;
26767+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
26768+ err = -EINVAL;
26769+ skipped = 0;
26770+ token = match_token(opt_str, options, a->args);
26771+ switch (token) {
26772+ case Opt_br:
26773+ err = 0;
26774+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
26775+ && *opt_str) {
26776+ err = opt_add(opt, opt_str, opts->sb_flags,
26777+ bindex++);
26778+ if (unlikely(!err && ++opt > opt_tail)) {
26779+ err = -E2BIG;
26780+ break;
26781+ }
26782+ opt->type = Opt_tail;
26783+ skipped = 1;
26784+ }
26785+ break;
26786+ case Opt_add:
26787+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26788+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26789+ break;
26790+ }
26791+ bindex = n;
26792+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
26793+ bindex);
26794+ if (!err)
26795+ opt->type = token;
26796+ break;
26797+ case Opt_append:
26798+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26799+ /*dummy bindex*/1);
26800+ if (!err)
26801+ opt->type = token;
26802+ break;
26803+ case Opt_prepend:
26804+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26805+ /*bindex*/0);
26806+ if (!err)
26807+ opt->type = token;
26808+ break;
26809+ case Opt_del:
26810+ err = au_opts_parse_del(&opt->del, a->args);
26811+ if (!err)
26812+ opt->type = token;
26813+ break;
26814+#if 0 /* reserved for future use */
26815+ case Opt_idel:
26816+ del->pathname = "(indexed)";
26817+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 26818+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26819+ break;
26820+ }
26821+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
26822+ if (!err)
26823+ opt->type = token;
26824+ break;
26825+#endif
26826+ case Opt_mod:
26827+ err = au_opts_parse_mod(&opt->mod, a->args);
26828+ if (!err)
26829+ opt->type = token;
26830+ break;
26831+#ifdef IMOD /* reserved for future use */
26832+ case Opt_imod:
26833+ u.mod->path = "(indexed)";
26834+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26835+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26836+ break;
26837+ }
26838+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
26839+ if (!err)
26840+ opt->type = token;
26841+ break;
26842+#endif
26843+ case Opt_xino:
26844+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
26845+ if (!err)
26846+ opt->type = token;
26847+ break;
26848+
26849+ case Opt_trunc_xino_path:
26850+ err = au_opts_parse_xino_itrunc_path
26851+ (sb, &opt->xino_itrunc, a->args);
26852+ if (!err)
26853+ opt->type = token;
26854+ break;
26855+
26856+ case Opt_itrunc_xino:
26857+ u.xino_itrunc = &opt->xino_itrunc;
26858+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26859+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26860+ break;
26861+ }
26862+ u.xino_itrunc->bindex = n;
26863+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26864+ if (n < 0 || au_sbbot(sb) < n) {
4a4d8108 26865+ pr_err("out of bounds, %d\n", n);
1facf9fc 26866+ aufs_read_unlock(root, !AuLock_IR);
26867+ break;
26868+ }
26869+ aufs_read_unlock(root, !AuLock_IR);
26870+ err = 0;
26871+ opt->type = token;
26872+ break;
26873+
26874+ case Opt_dirwh:
26875+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
26876+ break;
26877+ err = 0;
26878+ opt->type = token;
26879+ break;
26880+
26881+ case Opt_rdcache:
027c5e7a
AM
26882+ if (unlikely(match_int(&a->args[0], &n))) {
26883+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26884+ break;
027c5e7a
AM
26885+ }
26886+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
26887+ pr_err("rdcache must be smaller than %d\n",
26888+ AUFS_RDCACHE_MAX);
26889+ break;
26890+ }
26891+ opt->rdcache = n;
1facf9fc 26892+ err = 0;
26893+ opt->type = token;
26894+ break;
26895+ case Opt_rdblk:
26896+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26897+ || n < 0
1facf9fc 26898+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 26899+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26900+ break;
26901+ }
1308ab2a 26902+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
26903+ pr_err("rdblk must be larger than %d\n",
26904+ NAME_MAX);
1facf9fc 26905+ break;
26906+ }
26907+ opt->rdblk = n;
26908+ err = 0;
26909+ opt->type = token;
26910+ break;
26911+ case Opt_rdhash:
26912+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26913+ || n < 0
1facf9fc 26914+ || n * sizeof(struct hlist_head)
26915+ > KMALLOC_MAX_SIZE)) {
4a4d8108 26916+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26917+ break;
26918+ }
26919+ opt->rdhash = n;
26920+ err = 0;
26921+ opt->type = token;
26922+ break;
26923+
26924+ case Opt_trunc_xino:
26925+ case Opt_notrunc_xino:
26926+ case Opt_noxino:
26927+ case Opt_trunc_xib:
26928+ case Opt_notrunc_xib:
dece6358
AM
26929+ case Opt_shwh:
26930+ case Opt_noshwh:
076b876e
AM
26931+ case Opt_dirperm1:
26932+ case Opt_nodirperm1:
1facf9fc 26933+ case Opt_plink:
26934+ case Opt_noplink:
26935+ case Opt_list_plink:
4a4d8108
AM
26936+ case Opt_dio:
26937+ case Opt_nodio:
1facf9fc 26938+ case Opt_diropq_a:
26939+ case Opt_diropq_w:
26940+ case Opt_warn_perm:
26941+ case Opt_nowarn_perm:
1facf9fc 26942+ case Opt_verbose:
26943+ case Opt_noverbose:
26944+ case Opt_sum:
26945+ case Opt_nosum:
26946+ case Opt_wsum:
dece6358
AM
26947+ case Opt_rdblk_def:
26948+ case Opt_rdhash_def:
8b6a4947
AM
26949+ case Opt_dirren:
26950+ case Opt_nodirren:
c1595e42
JR
26951+ case Opt_acl:
26952+ case Opt_noacl:
1facf9fc 26953+ err = 0;
26954+ opt->type = token;
26955+ break;
26956+
26957+ case Opt_udba:
26958+ opt->udba = udba_val(a->args[0].from);
26959+ if (opt->udba >= 0) {
26960+ err = 0;
26961+ opt->type = token;
26962+ } else
4a4d8108 26963+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26964+ break;
26965+
26966+ case Opt_wbr_create:
26967+ u.create = &opt->wbr_create;
26968+ u.create->wbr_create
26969+ = au_wbr_create_val(a->args[0].from, u.create);
26970+ if (u.create->wbr_create >= 0) {
26971+ err = 0;
26972+ opt->type = token;
26973+ } else
4a4d8108 26974+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26975+ break;
26976+ case Opt_wbr_copyup:
26977+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
26978+ if (opt->wbr_copyup >= 0) {
26979+ err = 0;
26980+ opt->type = token;
26981+ } else
4a4d8108 26982+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26983+ break;
26984+
076b876e
AM
26985+ case Opt_fhsm_sec:
26986+ if (unlikely(match_int(&a->args[0], &n)
26987+ || n < 0)) {
26988+ pr_err("bad integer in %s\n", opt_str);
26989+ break;
26990+ }
26991+ if (sysaufs_brs) {
26992+ opt->fhsm_second = n;
26993+ opt->type = token;
26994+ } else
26995+ pr_warn("ignored %s\n", opt_str);
26996+ err = 0;
26997+ break;
26998+
1facf9fc 26999+ case Opt_ignore:
0c3ec466 27000+ pr_warn("ignored %s\n", opt_str);
1facf9fc 27001+ /*FALLTHROUGH*/
27002+ case Opt_ignore_silent:
27003+ skipped = 1;
27004+ err = 0;
27005+ break;
27006+ case Opt_err:
4a4d8108 27007+ pr_err("unknown option %s\n", opt_str);
1facf9fc 27008+ break;
27009+ }
27010+
27011+ if (!err && !skipped) {
27012+ if (unlikely(++opt > opt_tail)) {
27013+ err = -E2BIG;
27014+ opt--;
27015+ opt->type = Opt_tail;
27016+ break;
27017+ }
27018+ opt->type = Opt_tail;
27019+ }
27020+ }
27021+
9f237c51 27022+ au_kfree_rcu(a);
1facf9fc 27023+ dump_opts(opts);
27024+ if (unlikely(err))
27025+ au_opts_free(opts);
27026+
4f0767ce 27027+out:
1facf9fc 27028+ return err;
27029+}
27030+
27031+static int au_opt_wbr_create(struct super_block *sb,
27032+ struct au_opt_wbr_create *create)
27033+{
27034+ int err;
27035+ struct au_sbinfo *sbinfo;
27036+
dece6358
AM
27037+ SiMustWriteLock(sb);
27038+
1facf9fc 27039+ err = 1; /* handled */
27040+ sbinfo = au_sbi(sb);
27041+ if (sbinfo->si_wbr_create_ops->fin) {
27042+ err = sbinfo->si_wbr_create_ops->fin(sb);
27043+ if (!err)
27044+ err = 1;
27045+ }
27046+
27047+ sbinfo->si_wbr_create = create->wbr_create;
27048+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
27049+ switch (create->wbr_create) {
27050+ case AuWbrCreate_MFSRRV:
27051+ case AuWbrCreate_MFSRR:
f2c43d5f
AM
27052+ case AuWbrCreate_TDMFS:
27053+ case AuWbrCreate_TDMFSV:
392086de
AM
27054+ case AuWbrCreate_PMFSRR:
27055+ case AuWbrCreate_PMFSRRV:
1facf9fc 27056+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
27057+ /*FALLTHROUGH*/
27058+ case AuWbrCreate_MFS:
27059+ case AuWbrCreate_MFSV:
27060+ case AuWbrCreate_PMFS:
27061+ case AuWbrCreate_PMFSV:
e49829fe
JR
27062+ sbinfo->si_wbr_mfs.mfs_expire
27063+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 27064+ break;
27065+ }
27066+
27067+ if (sbinfo->si_wbr_create_ops->init)
27068+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
27069+
27070+ return err;
27071+}
27072+
27073+/*
27074+ * returns,
27075+ * plus: processed without an error
27076+ * zero: unprocessed
27077+ */
27078+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
27079+ struct au_opts *opts)
27080+{
27081+ int err;
27082+ struct au_sbinfo *sbinfo;
27083+
dece6358
AM
27084+ SiMustWriteLock(sb);
27085+
1facf9fc 27086+ err = 1; /* handled */
27087+ sbinfo = au_sbi(sb);
27088+ switch (opt->type) {
27089+ case Opt_udba:
27090+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
27091+ sbinfo->si_mntflags |= opt->udba;
27092+ opts->given_udba |= opt->udba;
27093+ break;
27094+
27095+ case Opt_plink:
27096+ au_opt_set(sbinfo->si_mntflags, PLINK);
27097+ break;
27098+ case Opt_noplink:
27099+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 27100+ au_plink_put(sb, /*verbose*/1);
1facf9fc 27101+ au_opt_clr(sbinfo->si_mntflags, PLINK);
27102+ break;
27103+ case Opt_list_plink:
27104+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
27105+ au_plink_list(sb);
27106+ break;
27107+
4a4d8108
AM
27108+ case Opt_dio:
27109+ au_opt_set(sbinfo->si_mntflags, DIO);
27110+ au_fset_opts(opts->flags, REFRESH_DYAOP);
27111+ break;
27112+ case Opt_nodio:
27113+ au_opt_clr(sbinfo->si_mntflags, DIO);
27114+ au_fset_opts(opts->flags, REFRESH_DYAOP);
27115+ break;
27116+
076b876e
AM
27117+ case Opt_fhsm_sec:
27118+ au_fhsm_set(sbinfo, opt->fhsm_second);
27119+ break;
27120+
1facf9fc 27121+ case Opt_diropq_a:
27122+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
27123+ break;
27124+ case Opt_diropq_w:
27125+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
27126+ break;
27127+
27128+ case Opt_warn_perm:
27129+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
27130+ break;
27131+ case Opt_nowarn_perm:
27132+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
27133+ break;
27134+
1facf9fc 27135+ case Opt_verbose:
27136+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
27137+ break;
27138+ case Opt_noverbose:
27139+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
27140+ break;
27141+
27142+ case Opt_sum:
27143+ au_opt_set(sbinfo->si_mntflags, SUM);
27144+ break;
27145+ case Opt_wsum:
27146+ au_opt_clr(sbinfo->si_mntflags, SUM);
27147+ au_opt_set(sbinfo->si_mntflags, SUM_W);
27148+ case Opt_nosum:
27149+ au_opt_clr(sbinfo->si_mntflags, SUM);
27150+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
27151+ break;
27152+
27153+ case Opt_wbr_create:
27154+ err = au_opt_wbr_create(sb, &opt->wbr_create);
27155+ break;
27156+ case Opt_wbr_copyup:
27157+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
27158+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
27159+ break;
27160+
27161+ case Opt_dirwh:
27162+ sbinfo->si_dirwh = opt->dirwh;
27163+ break;
27164+
27165+ case Opt_rdcache:
e49829fe
JR
27166+ sbinfo->si_rdcache
27167+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 27168+ break;
27169+ case Opt_rdblk:
27170+ sbinfo->si_rdblk = opt->rdblk;
27171+ break;
dece6358
AM
27172+ case Opt_rdblk_def:
27173+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
27174+ break;
1facf9fc 27175+ case Opt_rdhash:
27176+ sbinfo->si_rdhash = opt->rdhash;
27177+ break;
dece6358
AM
27178+ case Opt_rdhash_def:
27179+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
27180+ break;
27181+
27182+ case Opt_shwh:
27183+ au_opt_set(sbinfo->si_mntflags, SHWH);
27184+ break;
27185+ case Opt_noshwh:
27186+ au_opt_clr(sbinfo->si_mntflags, SHWH);
27187+ break;
1facf9fc 27188+
076b876e
AM
27189+ case Opt_dirperm1:
27190+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
27191+ break;
27192+ case Opt_nodirperm1:
27193+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
27194+ break;
27195+
1facf9fc 27196+ case Opt_trunc_xino:
27197+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
27198+ break;
27199+ case Opt_notrunc_xino:
27200+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
27201+ break;
27202+
27203+ case Opt_trunc_xino_path:
27204+ case Opt_itrunc_xino:
acd2b654
AM
27205+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex,
27206+ /*idx_begin*/0);
1facf9fc 27207+ if (!err)
27208+ err = 1;
27209+ break;
27210+
27211+ case Opt_trunc_xib:
27212+ au_fset_opts(opts->flags, TRUNC_XIB);
27213+ break;
27214+ case Opt_notrunc_xib:
27215+ au_fclr_opts(opts->flags, TRUNC_XIB);
27216+ break;
27217+
8b6a4947
AM
27218+ case Opt_dirren:
27219+ err = 1;
27220+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27221+ err = au_dr_opt_set(sb);
27222+ if (!err)
27223+ err = 1;
27224+ }
27225+ if (err == 1)
27226+ au_opt_set(sbinfo->si_mntflags, DIRREN);
27227+ break;
27228+ case Opt_nodirren:
27229+ err = 1;
27230+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27231+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags,
27232+ DR_FLUSHED));
27233+ if (!err)
27234+ err = 1;
27235+ }
27236+ if (err == 1)
27237+ au_opt_clr(sbinfo->si_mntflags, DIRREN);
27238+ break;
27239+
c1595e42 27240+ case Opt_acl:
2121bcd9 27241+ sb->s_flags |= SB_POSIXACL;
c1595e42
JR
27242+ break;
27243+ case Opt_noacl:
2121bcd9 27244+ sb->s_flags &= ~SB_POSIXACL;
c1595e42
JR
27245+ break;
27246+
1facf9fc 27247+ default:
27248+ err = 0;
27249+ break;
27250+ }
27251+
27252+ return err;
27253+}
27254+
27255+/*
27256+ * returns tri-state.
27257+ * plus: processed without an error
27258+ * zero: unprocessed
27259+ * minus: error
27260+ */
27261+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
27262+ struct au_opts *opts)
27263+{
27264+ int err, do_refresh;
27265+
27266+ err = 0;
27267+ switch (opt->type) {
27268+ case Opt_append:
5afbbe0d 27269+ opt->add.bindex = au_sbbot(sb) + 1;
1facf9fc 27270+ if (opt->add.bindex < 0)
27271+ opt->add.bindex = 0;
27272+ goto add;
27273+ case Opt_prepend:
27274+ opt->add.bindex = 0;
f6b6e03d 27275+ add: /* indented label */
1facf9fc 27276+ case Opt_add:
27277+ err = au_br_add(sb, &opt->add,
27278+ au_ftest_opts(opts->flags, REMOUNT));
27279+ if (!err) {
27280+ err = 1;
027c5e7a 27281+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27282+ }
27283+ break;
27284+
27285+ case Opt_del:
27286+ case Opt_idel:
27287+ err = au_br_del(sb, &opt->del,
27288+ au_ftest_opts(opts->flags, REMOUNT));
27289+ if (!err) {
27290+ err = 1;
27291+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 27292+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27293+ }
27294+ break;
27295+
27296+ case Opt_mod:
27297+ case Opt_imod:
27298+ err = au_br_mod(sb, &opt->mod,
27299+ au_ftest_opts(opts->flags, REMOUNT),
27300+ &do_refresh);
27301+ if (!err) {
27302+ err = 1;
027c5e7a
AM
27303+ if (do_refresh)
27304+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27305+ }
27306+ break;
27307+ }
1facf9fc 27308+ return err;
27309+}
27310+
27311+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
27312+ struct au_opt_xino **opt_xino,
27313+ struct au_opts *opts)
27314+{
27315+ int err;
1facf9fc 27316+
27317+ err = 0;
27318+ switch (opt->type) {
27319+ case Opt_xino:
062440b3
AM
27320+ err = au_xino_set(sb, &opt->xino,
27321+ !!au_ftest_opts(opts->flags, REMOUNT));
27322+ if (unlikely(err))
27323+ break;
27324+
27325+ *opt_xino = &opt->xino;
1facf9fc 27326+ break;
27327+
27328+ case Opt_noxino:
27329+ au_xino_clr(sb);
1facf9fc 27330+ *opt_xino = (void *)-1;
27331+ break;
27332+ }
27333+
27334+ return err;
27335+}
27336+
27337+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27338+ unsigned int pending)
27339+{
076b876e 27340+ int err, fhsm;
5afbbe0d 27341+ aufs_bindex_t bindex, bbot;
79b8bda9 27342+ unsigned char do_plink, skip, do_free, can_no_dreval;
1facf9fc 27343+ struct au_branch *br;
27344+ struct au_wbr *wbr;
79b8bda9 27345+ struct dentry *root, *dentry;
1facf9fc 27346+ struct inode *dir, *h_dir;
27347+ struct au_sbinfo *sbinfo;
27348+ struct au_hinode *hdir;
27349+
dece6358
AM
27350+ SiMustAnyLock(sb);
27351+
1facf9fc 27352+ sbinfo = au_sbi(sb);
27353+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
27354+
2121bcd9 27355+ if (!(sb_flags & SB_RDONLY)) {
dece6358 27356+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 27357+ pr_warn("first branch should be rw\n");
dece6358 27358+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
febd17d6 27359+ pr_warn_once("shwh should be used with ro\n");
dece6358 27360+ }
1facf9fc 27361+
4a4d8108 27362+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 27363+ && !au_opt_test(sbinfo->si_mntflags, XINO))
febd17d6 27364+ pr_warn_once("udba=*notify requires xino\n");
1facf9fc 27365+
076b876e 27366+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1))
febd17d6
JR
27367+ pr_warn_once("dirperm1 breaks the protection"
27368+ " by the permission bits on the lower branch\n");
076b876e 27369+
1facf9fc 27370+ err = 0;
076b876e 27371+ fhsm = 0;
1facf9fc 27372+ root = sb->s_root;
5527c038 27373+ dir = d_inode(root);
1facf9fc 27374+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
79b8bda9
AM
27375+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending),
27376+ UDBA_NONE);
5afbbe0d
AM
27377+ bbot = au_sbbot(sb);
27378+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
1facf9fc 27379+ skip = 0;
27380+ h_dir = au_h_iptr(dir, bindex);
27381+ br = au_sbr(sb, bindex);
1facf9fc 27382+
c1595e42
JR
27383+ if ((br->br_perm & AuBrAttr_ICEX)
27384+ && !h_dir->i_op->listxattr)
27385+ br->br_perm &= ~AuBrAttr_ICEX;
27386+#if 0
27387+ if ((br->br_perm & AuBrAttr_ICEX_SEC)
2121bcd9 27388+ && (au_br_sb(br)->s_flags & SB_NOSEC))
c1595e42
JR
27389+ br->br_perm &= ~AuBrAttr_ICEX_SEC;
27390+#endif
27391+
27392+ do_free = 0;
1facf9fc 27393+ wbr = br->br_wbr;
27394+ if (wbr)
27395+ wbr_wh_read_lock(wbr);
27396+
1e00d052 27397+ if (!au_br_writable(br->br_perm)) {
1facf9fc 27398+ do_free = !!wbr;
27399+ skip = (!wbr
27400+ || (!wbr->wbr_whbase
27401+ && !wbr->wbr_plink
27402+ && !wbr->wbr_orph));
1e00d052 27403+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 27404+ /* skip = (!br->br_whbase && !br->br_orph); */
27405+ skip = (!wbr || !wbr->wbr_whbase);
27406+ if (skip && wbr) {
27407+ if (do_plink)
27408+ skip = !!wbr->wbr_plink;
27409+ else
27410+ skip = !wbr->wbr_plink;
27411+ }
1e00d052 27412+ } else {
1facf9fc 27413+ /* skip = (br->br_whbase && br->br_ohph); */
27414+ skip = (wbr && wbr->wbr_whbase);
27415+ if (skip) {
27416+ if (do_plink)
27417+ skip = !!wbr->wbr_plink;
27418+ else
27419+ skip = !wbr->wbr_plink;
27420+ }
1facf9fc 27421+ }
27422+ if (wbr)
27423+ wbr_wh_read_unlock(wbr);
27424+
79b8bda9
AM
27425+ if (can_no_dreval) {
27426+ dentry = br->br_path.dentry;
27427+ spin_lock(&dentry->d_lock);
27428+ if (dentry->d_flags &
27429+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE))
27430+ can_no_dreval = 0;
27431+ spin_unlock(&dentry->d_lock);
27432+ }
27433+
076b876e
AM
27434+ if (au_br_fhsm(br->br_perm)) {
27435+ fhsm++;
27436+ AuDebugOn(!br->br_fhsm);
27437+ }
27438+
1facf9fc 27439+ if (skip)
27440+ continue;
27441+
27442+ hdir = au_hi(dir, bindex);
5afbbe0d 27443+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 27444+ if (wbr)
27445+ wbr_wh_write_lock(wbr);
86dc4139 27446+ err = au_wh_init(br, sb);
1facf9fc 27447+ if (wbr)
27448+ wbr_wh_write_unlock(wbr);
5afbbe0d 27449+ au_hn_inode_unlock(hdir);
1facf9fc 27450+
27451+ if (!err && do_free) {
9f237c51 27452+ au_kfree_rcu(wbr);
1facf9fc 27453+ br->br_wbr = NULL;
27454+ }
27455+ }
27456+
79b8bda9
AM
27457+ if (can_no_dreval)
27458+ au_fset_si(sbinfo, NO_DREVAL);
27459+ else
27460+ au_fclr_si(sbinfo, NO_DREVAL);
27461+
c1595e42 27462+ if (fhsm >= 2) {
076b876e 27463+ au_fset_si(sbinfo, FHSM);
5afbbe0d 27464+ for (bindex = bbot; bindex >= 0; bindex--) {
c1595e42
JR
27465+ br = au_sbr(sb, bindex);
27466+ if (au_br_fhsm(br->br_perm)) {
27467+ au_fhsm_set_bottom(sb, bindex);
27468+ break;
27469+ }
27470+ }
27471+ } else {
076b876e 27472+ au_fclr_si(sbinfo, FHSM);
c1595e42
JR
27473+ au_fhsm_set_bottom(sb, -1);
27474+ }
076b876e 27475+
1facf9fc 27476+ return err;
27477+}
27478+
27479+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
27480+{
27481+ int err;
27482+ unsigned int tmp;
5afbbe0d 27483+ aufs_bindex_t bindex, bbot;
1facf9fc 27484+ struct au_opt *opt;
27485+ struct au_opt_xino *opt_xino, xino;
27486+ struct au_sbinfo *sbinfo;
027c5e7a 27487+ struct au_branch *br;
076b876e 27488+ struct inode *dir;
1facf9fc 27489+
dece6358
AM
27490+ SiMustWriteLock(sb);
27491+
1facf9fc 27492+ err = 0;
27493+ opt_xino = NULL;
27494+ opt = opts->opt;
27495+ while (err >= 0 && opt->type != Opt_tail)
27496+ err = au_opt_simple(sb, opt++, opts);
27497+ if (err > 0)
27498+ err = 0;
27499+ else if (unlikely(err < 0))
27500+ goto out;
27501+
27502+ /* disable xino and udba temporary */
27503+ sbinfo = au_sbi(sb);
27504+ tmp = sbinfo->si_mntflags;
27505+ au_opt_clr(sbinfo->si_mntflags, XINO);
27506+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
27507+
27508+ opt = opts->opt;
27509+ while (err >= 0 && opt->type != Opt_tail)
27510+ err = au_opt_br(sb, opt++, opts);
27511+ if (err > 0)
27512+ err = 0;
27513+ else if (unlikely(err < 0))
27514+ goto out;
27515+
5afbbe0d
AM
27516+ bbot = au_sbbot(sb);
27517+ if (unlikely(bbot < 0)) {
1facf9fc 27518+ err = -EINVAL;
4a4d8108 27519+ pr_err("no branches\n");
1facf9fc 27520+ goto out;
27521+ }
27522+
27523+ if (au_opt_test(tmp, XINO))
27524+ au_opt_set(sbinfo->si_mntflags, XINO);
27525+ opt = opts->opt;
27526+ while (!err && opt->type != Opt_tail)
27527+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
27528+ if (unlikely(err))
27529+ goto out;
27530+
27531+ err = au_opts_verify(sb, sb->s_flags, tmp);
27532+ if (unlikely(err))
27533+ goto out;
27534+
27535+ /* restore xino */
27536+ if (au_opt_test(tmp, XINO) && !opt_xino) {
27537+ xino.file = au_xino_def(sb);
27538+ err = PTR_ERR(xino.file);
27539+ if (IS_ERR(xino.file))
27540+ goto out;
27541+
27542+ err = au_xino_set(sb, &xino, /*remount*/0);
27543+ fput(xino.file);
27544+ if (unlikely(err))
27545+ goto out;
27546+ }
27547+
27548+ /* restore udba */
027c5e7a 27549+ tmp &= AuOptMask_UDBA;
1facf9fc 27550+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a 27551+ sbinfo->si_mntflags |= tmp;
5afbbe0d
AM
27552+ bbot = au_sbbot(sb);
27553+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
27554+ br = au_sbr(sb, bindex);
27555+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
27556+ if (unlikely(err))
27557+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
27558+ bindex, err);
27559+ /* go on even if err */
27560+ }
4a4d8108 27561+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
5527c038 27562+ dir = d_inode(sb->s_root);
4a4d8108 27563+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 27564+ }
27565+
4f0767ce 27566+out:
1facf9fc 27567+ return err;
27568+}
27569+
27570+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
27571+{
27572+ int err, rerr;
79b8bda9 27573+ unsigned char no_dreval;
1facf9fc 27574+ struct inode *dir;
27575+ struct au_opt_xino *opt_xino;
27576+ struct au_opt *opt;
27577+ struct au_sbinfo *sbinfo;
27578+
dece6358
AM
27579+ SiMustWriteLock(sb);
27580+
8b6a4947
AM
27581+ err = au_dr_opt_flush(sb);
27582+ if (unlikely(err))
27583+ goto out;
27584+ au_fset_opts(opts->flags, DR_FLUSHED);
27585+
5527c038 27586+ dir = d_inode(sb->s_root);
1facf9fc 27587+ sbinfo = au_sbi(sb);
1facf9fc 27588+ opt_xino = NULL;
27589+ opt = opts->opt;
27590+ while (err >= 0 && opt->type != Opt_tail) {
27591+ err = au_opt_simple(sb, opt, opts);
27592+ if (!err)
27593+ err = au_opt_br(sb, opt, opts);
27594+ if (!err)
27595+ err = au_opt_xino(sb, opt, &opt_xino, opts);
27596+ opt++;
27597+ }
27598+ if (err > 0)
27599+ err = 0;
27600+ AuTraceErr(err);
27601+ /* go on even err */
27602+
79b8bda9 27603+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
1facf9fc 27604+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
27605+ if (unlikely(rerr && !err))
27606+ err = rerr;
27607+
79b8bda9 27608+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
b95c5147 27609+ au_fset_opts(opts->flags, REFRESH_IDOP);
79b8bda9 27610+
1facf9fc 27611+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
27612+ rerr = au_xib_trunc(sb);
27613+ if (unlikely(rerr && !err))
27614+ err = rerr;
27615+ }
27616+
27617+ /* will be handled by the caller */
027c5e7a 27618+ if (!au_ftest_opts(opts->flags, REFRESH)
79b8bda9
AM
27619+ && (opts->given_udba
27620+ || au_opt_test(sbinfo->si_mntflags, XINO)
b95c5147 27621+ || au_ftest_opts(opts->flags, REFRESH_IDOP)
79b8bda9 27622+ ))
027c5e7a 27623+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27624+
27625+ AuDbg("status 0x%x\n", opts->flags);
8b6a4947
AM
27626+
27627+out:
1facf9fc 27628+ return err;
27629+}
27630+
27631+/* ---------------------------------------------------------------------- */
27632+
27633+unsigned int au_opt_udba(struct super_block *sb)
27634+{
27635+ return au_mntflags(sb) & AuOptMask_UDBA;
27636+}
7f207e10 27637diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
fbc438ed
JR
27638--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 08:00:00.000000000 +0800
27639+++ linux/fs/aufs/opts.h 2019-07-11 21:21:54.382384486 +0800
062440b3
AM
27640@@ -0,0 +1,225 @@
27641+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 27642+/*
ba1aed25 27643+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 27644+ *
27645+ * This program, aufs is free software; you can redistribute it and/or modify
27646+ * it under the terms of the GNU General Public License as published by
27647+ * the Free Software Foundation; either version 2 of the License, or
27648+ * (at your option) any later version.
dece6358
AM
27649+ *
27650+ * This program is distributed in the hope that it will be useful,
27651+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27652+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27653+ * GNU General Public License for more details.
27654+ *
27655+ * You should have received a copy of the GNU General Public License
523b37e3 27656+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27657+ */
27658+
27659+/*
27660+ * mount options/flags
27661+ */
27662+
27663+#ifndef __AUFS_OPTS_H__
27664+#define __AUFS_OPTS_H__
27665+
27666+#ifdef __KERNEL__
27667+
dece6358 27668+#include <linux/path.h>
1facf9fc 27669+
dece6358 27670+struct file;
dece6358 27671+
1facf9fc 27672+/* ---------------------------------------------------------------------- */
27673+
27674+/* mount flags */
27675+#define AuOpt_XINO 1 /* external inode number bitmap
27676+ and translation table */
27677+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
27678+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
27679+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 27680+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
27681+#define AuOpt_SHWH (1 << 5) /* show whiteout */
27682+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
076b876e
AM
27683+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm
27684+ bits */
dece6358
AM
27685+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
27686+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
27687+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
27688+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
eca801bf 27689+#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */
4a4d8108 27690+#define AuOpt_DIO (1 << 14) /* direct io */
8b6a4947 27691+#define AuOpt_DIRREN (1 << 15) /* directory rename */
1facf9fc 27692+
4a4d8108
AM
27693+#ifndef CONFIG_AUFS_HNOTIFY
27694+#undef AuOpt_UDBA_HNOTIFY
27695+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 27696+#endif
8b6a4947
AM
27697+#ifndef CONFIG_AUFS_DIRREN
27698+#undef AuOpt_DIRREN
27699+#define AuOpt_DIRREN 0
27700+#endif
dece6358
AM
27701+#ifndef CONFIG_AUFS_SHWH
27702+#undef AuOpt_SHWH
27703+#define AuOpt_SHWH 0
27704+#endif
1facf9fc 27705+
27706+#define AuOpt_Def (AuOpt_XINO \
27707+ | AuOpt_UDBA_REVAL \
27708+ | AuOpt_PLINK \
27709+ /* | AuOpt_DIRPERM1 */ \
27710+ | AuOpt_WARN_PERM)
27711+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
27712+ | AuOpt_UDBA_REVAL \
4a4d8108 27713+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 27714+
27715+#define au_opt_test(flags, name) (flags & AuOpt_##name)
27716+#define au_opt_set(flags, name) do { \
27717+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
27718+ ((flags) |= AuOpt_##name); \
27719+} while (0)
27720+#define au_opt_set_udba(flags, name) do { \
27721+ (flags) &= ~AuOptMask_UDBA; \
27722+ ((flags) |= AuOpt_##name); \
27723+} while (0)
7f207e10
AM
27724+#define au_opt_clr(flags, name) do { \
27725+ ((flags) &= ~AuOpt_##name); \
27726+} while (0)
1facf9fc 27727+
e49829fe
JR
27728+static inline unsigned int au_opts_plink(unsigned int mntflags)
27729+{
27730+#ifdef CONFIG_PROC_FS
27731+ return mntflags;
27732+#else
27733+ return mntflags & ~AuOpt_PLINK;
27734+#endif
27735+}
27736+
1facf9fc 27737+/* ---------------------------------------------------------------------- */
27738+
27739+/* policies to select one among multiple writable branches */
27740+enum {
27741+ AuWbrCreate_TDP, /* top down parent */
27742+ AuWbrCreate_RR, /* round robin */
27743+ AuWbrCreate_MFS, /* most free space */
27744+ AuWbrCreate_MFSV, /* mfs with seconds */
27745+ AuWbrCreate_MFSRR, /* mfs then rr */
27746+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
f2c43d5f
AM
27747+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */
27748+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */
1facf9fc 27749+ AuWbrCreate_PMFS, /* parent and mfs */
27750+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
392086de
AM
27751+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */
27752+ AuWbrCreate_PMFSRRV, /* plus seconds */
1facf9fc 27753+
27754+ AuWbrCreate_Def = AuWbrCreate_TDP
27755+};
27756+
27757+enum {
27758+ AuWbrCopyup_TDP, /* top down parent */
27759+ AuWbrCopyup_BUP, /* bottom up parent */
27760+ AuWbrCopyup_BU, /* bottom up */
27761+
27762+ AuWbrCopyup_Def = AuWbrCopyup_TDP
27763+};
27764+
27765+/* ---------------------------------------------------------------------- */
27766+
27767+struct au_opt_add {
27768+ aufs_bindex_t bindex;
27769+ char *pathname;
27770+ int perm;
27771+ struct path path;
27772+};
27773+
27774+struct au_opt_del {
27775+ char *pathname;
27776+ struct path h_path;
27777+};
27778+
27779+struct au_opt_mod {
27780+ char *path;
27781+ int perm;
27782+ struct dentry *h_root;
27783+};
27784+
27785+struct au_opt_xino {
27786+ char *path;
27787+ struct file *file;
27788+};
27789+
27790+struct au_opt_xino_itrunc {
27791+ aufs_bindex_t bindex;
27792+};
27793+
27794+struct au_opt_wbr_create {
27795+ int wbr_create;
27796+ int mfs_second;
27797+ unsigned long long mfsrr_watermark;
27798+};
27799+
27800+struct au_opt {
27801+ int type;
27802+ union {
27803+ struct au_opt_xino xino;
27804+ struct au_opt_xino_itrunc xino_itrunc;
27805+ struct au_opt_add add;
27806+ struct au_opt_del del;
27807+ struct au_opt_mod mod;
27808+ int dirwh;
27809+ int rdcache;
27810+ unsigned int rdblk;
27811+ unsigned int rdhash;
27812+ int udba;
27813+ struct au_opt_wbr_create wbr_create;
27814+ int wbr_copyup;
076b876e 27815+ unsigned int fhsm_second;
1facf9fc 27816+ };
27817+};
27818+
27819+/* opts flags */
27820+#define AuOpts_REMOUNT 1
027c5e7a
AM
27821+#define AuOpts_REFRESH (1 << 1)
27822+#define AuOpts_TRUNC_XIB (1 << 2)
27823+#define AuOpts_REFRESH_DYAOP (1 << 3)
b95c5147 27824+#define AuOpts_REFRESH_IDOP (1 << 4)
8b6a4947 27825+#define AuOpts_DR_FLUSHED (1 << 5)
1facf9fc 27826+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
27827+#define au_fset_opts(flags, name) \
27828+ do { (flags) |= AuOpts_##name; } while (0)
27829+#define au_fclr_opts(flags, name) \
27830+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 27831+
8b6a4947
AM
27832+#ifndef CONFIG_AUFS_DIRREN
27833+#undef AuOpts_DR_FLUSHED
27834+#define AuOpts_DR_FLUSHED 0
27835+#endif
27836+
1facf9fc 27837+struct au_opts {
27838+ struct au_opt *opt;
27839+ int max_opt;
27840+
27841+ unsigned int given_udba;
27842+ unsigned int flags;
27843+ unsigned long sb_flags;
27844+};
27845+
27846+/* ---------------------------------------------------------------------- */
27847+
7e9cd9fe 27848+/* opts.c */
076b876e 27849+void au_optstr_br_perm(au_br_perm_str_t *str, int perm);
1facf9fc 27850+const char *au_optstr_udba(int udba);
27851+const char *au_optstr_wbr_copyup(int wbr_copyup);
27852+const char *au_optstr_wbr_create(int wbr_create);
27853+
27854+void au_opts_free(struct au_opts *opts);
3c1bdaff 27855+struct super_block;
1facf9fc 27856+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
27857+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27858+ unsigned int pending);
27859+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
27860+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
27861+
27862+unsigned int au_opt_udba(struct super_block *sb);
27863+
1facf9fc 27864+#endif /* __KERNEL__ */
27865+#endif /* __AUFS_OPTS_H__ */
7f207e10 27866diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
fbc438ed
JR
27867--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 08:00:00.000000000 +0800
27868+++ linux/fs/aufs/plink.c 2019-07-11 21:21:54.382384486 +0800
062440b3 27869@@ -0,0 +1,516 @@
cd7a4cd9 27870+// SPDX-License-Identifier: GPL-2.0
1facf9fc 27871+/*
ba1aed25 27872+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 27873+ *
27874+ * This program, aufs is free software; you can redistribute it and/or modify
27875+ * it under the terms of the GNU General Public License as published by
27876+ * the Free Software Foundation; either version 2 of the License, or
27877+ * (at your option) any later version.
dece6358
AM
27878+ *
27879+ * This program is distributed in the hope that it will be useful,
27880+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27881+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27882+ * GNU General Public License for more details.
27883+ *
27884+ * You should have received a copy of the GNU General Public License
523b37e3 27885+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27886+ */
27887+
27888+/*
27889+ * pseudo-link
27890+ */
27891+
27892+#include "aufs.h"
27893+
27894+/*
e49829fe 27895+ * the pseudo-link maintenance mode.
1facf9fc 27896+ * during a user process maintains the pseudo-links,
27897+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
27898+ *
27899+ * Flags
27900+ * NOPLM:
27901+ * For entry functions which will handle plink, and i_mutex is already held
27902+ * in VFS.
27903+ * They cannot wait and should return an error at once.
27904+ * Callers has to check the error.
27905+ * NOPLMW:
27906+ * For entry functions which will handle plink, but i_mutex is not held
27907+ * in VFS.
27908+ * They can wait the plink maintenance mode to finish.
27909+ *
27910+ * They behave like F_SETLK and F_SETLKW.
27911+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 27912+ */
e49829fe
JR
27913+
27914+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 27915+{
e49829fe
JR
27916+ int err;
27917+ pid_t pid, ppid;
f0c0a007 27918+ struct task_struct *parent, *prev;
e49829fe 27919+ struct au_sbinfo *sbi;
dece6358
AM
27920+
27921+ SiMustAnyLock(sb);
27922+
e49829fe
JR
27923+ err = 0;
27924+ if (!au_opt_test(au_mntflags(sb), PLINK))
27925+ goto out;
27926+
27927+ sbi = au_sbi(sb);
27928+ pid = sbi->si_plink_maint_pid;
27929+ if (!pid || pid == current->pid)
27930+ goto out;
27931+
27932+ /* todo: it highly depends upon /sbin/mount.aufs */
f0c0a007
AM
27933+ prev = NULL;
27934+ parent = current;
27935+ ppid = 0;
e49829fe 27936+ rcu_read_lock();
f0c0a007
AM
27937+ while (1) {
27938+ parent = rcu_dereference(parent->real_parent);
27939+ if (parent == prev)
27940+ break;
27941+ ppid = task_pid_vnr(parent);
27942+ if (pid == ppid) {
27943+ rcu_read_unlock();
27944+ goto out;
27945+ }
27946+ prev = parent;
27947+ }
e49829fe 27948+ rcu_read_unlock();
e49829fe
JR
27949+
27950+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
27951+ /* if there is no i_mutex lock in VFS, we don't need to wait */
27952+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
27953+ while (sbi->si_plink_maint_pid) {
27954+ si_read_unlock(sb);
27955+ /* gave up wake_up_bit() */
27956+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
27957+
27958+ if (au_ftest_lock(flags, FLUSH))
27959+ au_nwt_flush(&sbi->si_nowait);
27960+ si_noflush_read_lock(sb);
27961+ }
27962+ } else if (au_ftest_lock(flags, NOPLM)) {
27963+ AuDbg("ppid %d, pid %d\n", ppid, pid);
27964+ err = -EAGAIN;
27965+ }
27966+
27967+out:
27968+ return err;
4a4d8108
AM
27969+}
27970+
e49829fe 27971+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 27972+{
4a4d8108 27973+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 27974+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 27975+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 27976+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
27977+}
27978+
e49829fe 27979+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
27980+{
27981+ int err;
4a4d8108
AM
27982+ struct au_sbinfo *sbinfo;
27983+
27984+ err = 0;
4a4d8108
AM
27985+ sbinfo = au_sbi(sb);
27986+ /* make sure i am the only one in this fs */
e49829fe
JR
27987+ si_write_lock(sb, AuLock_FLUSH);
27988+ if (au_opt_test(au_mntflags(sb), PLINK)) {
27989+ spin_lock(&sbinfo->si_plink_maint_lock);
27990+ if (!sbinfo->si_plink_maint_pid)
27991+ sbinfo->si_plink_maint_pid = current->pid;
27992+ else
27993+ err = -EBUSY;
27994+ spin_unlock(&sbinfo->si_plink_maint_lock);
27995+ }
4a4d8108
AM
27996+ si_write_unlock(sb);
27997+
27998+ return err;
1facf9fc 27999+}
28000+
28001+/* ---------------------------------------------------------------------- */
28002+
1facf9fc 28003+#ifdef CONFIG_AUFS_DEBUG
28004+void au_plink_list(struct super_block *sb)
28005+{
86dc4139 28006+ int i;
1facf9fc 28007+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28008+ struct hlist_bl_head *hbl;
28009+ struct hlist_bl_node *pos;
5afbbe0d 28010+ struct au_icntnr *icntnr;
1facf9fc 28011+
dece6358
AM
28012+ SiMustAnyLock(sb);
28013+
1facf9fc 28014+ sbinfo = au_sbi(sb);
28015+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28016+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28017+
86dc4139 28018+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28019+ hbl = sbinfo->si_plink + i;
28020+ hlist_bl_lock(hbl);
28021+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 28022+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino);
8b6a4947 28023+ hlist_bl_unlock(hbl);
86dc4139 28024+ }
1facf9fc 28025+}
28026+#endif
28027+
28028+/* is the inode pseudo-linked? */
28029+int au_plink_test(struct inode *inode)
28030+{
86dc4139 28031+ int found, i;
1facf9fc 28032+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28033+ struct hlist_bl_head *hbl;
28034+ struct hlist_bl_node *pos;
5afbbe0d 28035+ struct au_icntnr *icntnr;
1facf9fc 28036+
28037+ sbinfo = au_sbi(inode->i_sb);
dece6358 28038+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 28039+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 28040+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 28041+
28042+ found = 0;
86dc4139 28043+ i = au_plink_hash(inode->i_ino);
8b6a4947
AM
28044+ hbl = sbinfo->si_plink + i;
28045+ hlist_bl_lock(hbl);
28046+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 28047+ if (&icntnr->vfs_inode == inode) {
1facf9fc 28048+ found = 1;
28049+ break;
28050+ }
8b6a4947 28051+ hlist_bl_unlock(hbl);
1facf9fc 28052+ return found;
28053+}
28054+
28055+/* ---------------------------------------------------------------------- */
28056+
28057+/*
28058+ * generate a name for plink.
28059+ * the file will be stored under AUFS_WH_PLINKDIR.
28060+ */
28061+/* 20 is max digits length of ulong 64 */
28062+#define PLINK_NAME_LEN ((20 + 1) * 2)
28063+
28064+static int plink_name(char *name, int len, struct inode *inode,
28065+ aufs_bindex_t bindex)
28066+{
28067+ int rlen;
28068+ struct inode *h_inode;
28069+
28070+ h_inode = au_h_iptr(inode, bindex);
28071+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
28072+ return rlen;
28073+}
28074+
7f207e10
AM
28075+struct au_do_plink_lkup_args {
28076+ struct dentry **errp;
28077+ struct qstr *tgtname;
28078+ struct dentry *h_parent;
28079+ struct au_branch *br;
28080+};
28081+
28082+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
28083+ struct dentry *h_parent,
28084+ struct au_branch *br)
28085+{
28086+ struct dentry *h_dentry;
febd17d6 28087+ struct inode *h_inode;
7f207e10 28088+
febd17d6 28089+ h_inode = d_inode(h_parent);
be118d29 28090+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2);
b4510431 28091+ h_dentry = vfsub_lkup_one(tgtname, h_parent);
3c1bdaff 28092+ inode_unlock_shared(h_inode);
7f207e10
AM
28093+ return h_dentry;
28094+}
28095+
28096+static void au_call_do_plink_lkup(void *args)
28097+{
28098+ struct au_do_plink_lkup_args *a = args;
28099+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
28100+}
28101+
1facf9fc 28102+/* lookup the plink-ed @inode under the branch at @bindex */
28103+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
28104+{
28105+ struct dentry *h_dentry, *h_parent;
28106+ struct au_branch *br;
7f207e10 28107+ int wkq_err;
1facf9fc 28108+ char a[PLINK_NAME_LEN];
0c3ec466 28109+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 28110+
e49829fe
JR
28111+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
28112+
1facf9fc 28113+ br = au_sbr(inode->i_sb, bindex);
28114+ h_parent = br->br_wbr->wbr_plink;
1facf9fc 28115+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
28116+
2dfbb274 28117+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
28118+ struct au_do_plink_lkup_args args = {
28119+ .errp = &h_dentry,
28120+ .tgtname = &tgtname,
28121+ .h_parent = h_parent,
28122+ .br = br
28123+ };
28124+
28125+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
28126+ if (unlikely(wkq_err))
28127+ h_dentry = ERR_PTR(wkq_err);
28128+ } else
28129+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
28130+
1facf9fc 28131+ return h_dentry;
28132+}
28133+
28134+/* create a pseudo-link */
28135+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
28136+ struct dentry *h_dentry, struct au_branch *br)
28137+{
28138+ int err;
28139+ struct path h_path = {
86dc4139 28140+ .mnt = au_br_mnt(br)
1facf9fc 28141+ };
523b37e3 28142+ struct inode *h_dir, *delegated;
1facf9fc 28143+
5527c038 28144+ h_dir = d_inode(h_parent);
febd17d6 28145+ inode_lock_nested(h_dir, AuLsc_I_CHILD2);
4f0767ce 28146+again:
b4510431 28147+ h_path.dentry = vfsub_lkup_one(tgt, h_parent);
1facf9fc 28148+ err = PTR_ERR(h_path.dentry);
28149+ if (IS_ERR(h_path.dentry))
28150+ goto out;
28151+
28152+ err = 0;
28153+ /* wh.plink dir is not monitored */
7f207e10 28154+ /* todo: is it really safe? */
5527c038
JR
28155+ if (d_is_positive(h_path.dentry)
28156+ && d_inode(h_path.dentry) != d_inode(h_dentry)) {
523b37e3
AM
28157+ delegated = NULL;
28158+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0);
28159+ if (unlikely(err == -EWOULDBLOCK)) {
28160+ pr_warn("cannot retry for NFSv4 delegation"
28161+ " for an internal unlink\n");
28162+ iput(delegated);
28163+ }
1facf9fc 28164+ dput(h_path.dentry);
28165+ h_path.dentry = NULL;
28166+ if (!err)
28167+ goto again;
28168+ }
5527c038 28169+ if (!err && d_is_negative(h_path.dentry)) {
523b37e3
AM
28170+ delegated = NULL;
28171+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated);
28172+ if (unlikely(err == -EWOULDBLOCK)) {
28173+ pr_warn("cannot retry for NFSv4 delegation"
28174+ " for an internal link\n");
28175+ iput(delegated);
28176+ }
28177+ }
1facf9fc 28178+ dput(h_path.dentry);
28179+
4f0767ce 28180+out:
febd17d6 28181+ inode_unlock(h_dir);
1facf9fc 28182+ return err;
28183+}
28184+
28185+struct do_whplink_args {
28186+ int *errp;
28187+ struct qstr *tgt;
28188+ struct dentry *h_parent;
28189+ struct dentry *h_dentry;
28190+ struct au_branch *br;
28191+};
28192+
28193+static void call_do_whplink(void *args)
28194+{
28195+ struct do_whplink_args *a = args;
28196+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
28197+}
28198+
28199+static int whplink(struct dentry *h_dentry, struct inode *inode,
28200+ aufs_bindex_t bindex, struct au_branch *br)
28201+{
28202+ int err, wkq_err;
28203+ struct au_wbr *wbr;
28204+ struct dentry *h_parent;
1facf9fc 28205+ char a[PLINK_NAME_LEN];
0c3ec466 28206+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 28207+
28208+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
28209+ h_parent = wbr->wbr_plink;
1facf9fc 28210+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
28211+
28212+ /* always superio. */
2dfbb274 28213+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 28214+ struct do_whplink_args args = {
28215+ .errp = &err,
28216+ .tgt = &tgtname,
28217+ .h_parent = h_parent,
28218+ .h_dentry = h_dentry,
28219+ .br = br
28220+ };
28221+ wkq_err = au_wkq_wait(call_do_whplink, &args);
28222+ if (unlikely(wkq_err))
28223+ err = wkq_err;
28224+ } else
28225+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 28226+
28227+ return err;
28228+}
28229+
1facf9fc 28230+/*
28231+ * create a new pseudo-link for @h_dentry on @bindex.
28232+ * the linked inode is held in aufs @inode.
28233+ */
28234+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
28235+ struct dentry *h_dentry)
28236+{
28237+ struct super_block *sb;
28238+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28239+ struct hlist_bl_head *hbl;
28240+ struct hlist_bl_node *pos;
5afbbe0d 28241+ struct au_icntnr *icntnr;
86dc4139 28242+ int found, err, cnt, i;
1facf9fc 28243+
28244+ sb = inode->i_sb;
28245+ sbinfo = au_sbi(sb);
28246+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28247+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28248+
86dc4139 28249+ found = au_plink_test(inode);
4a4d8108 28250+ if (found)
1facf9fc 28251+ return;
4a4d8108 28252+
86dc4139 28253+ i = au_plink_hash(inode->i_ino);
8b6a4947 28254+ hbl = sbinfo->si_plink + i;
5afbbe0d 28255+ au_igrab(inode);
1facf9fc 28256+
8b6a4947
AM
28257+ hlist_bl_lock(hbl);
28258+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) {
5afbbe0d 28259+ if (&icntnr->vfs_inode == inode) {
4a4d8108
AM
28260+ found = 1;
28261+ break;
28262+ }
1facf9fc 28263+ }
5afbbe0d
AM
28264+ if (!found) {
28265+ icntnr = container_of(inode, struct au_icntnr, vfs_inode);
8b6a4947 28266+ hlist_bl_add_head(&icntnr->plink, hbl);
5afbbe0d 28267+ }
8b6a4947 28268+ hlist_bl_unlock(hbl);
4a4d8108 28269+ if (!found) {
8b6a4947 28270+ cnt = au_hbl_count(hbl);
acd2b654 28271+#define msg "unexpectedly unbalanced or too many pseudo-links"
86dc4139
AM
28272+ if (cnt > AUFS_PLINK_WARN)
28273+ AuWarn1(msg ", %d\n", cnt);
28274+#undef msg
1facf9fc 28275+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
5afbbe0d
AM
28276+ if (unlikely(err)) {
28277+ pr_warn("err %d, damaged pseudo link.\n", err);
8b6a4947 28278+ au_hbl_del(&icntnr->plink, hbl);
5afbbe0d 28279+ iput(&icntnr->vfs_inode);
4a4d8108 28280+ }
5afbbe0d
AM
28281+ } else
28282+ iput(&icntnr->vfs_inode);
1facf9fc 28283+}
28284+
28285+/* free all plinks */
e49829fe 28286+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 28287+{
86dc4139 28288+ int i, warned;
1facf9fc 28289+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28290+ struct hlist_bl_head *hbl;
28291+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28292+ struct au_icntnr *icntnr;
1facf9fc 28293+
dece6358
AM
28294+ SiMustWriteLock(sb);
28295+
1facf9fc 28296+ sbinfo = au_sbi(sb);
28297+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28298+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28299+
1facf9fc 28300+ /* no spin_lock since sbinfo is write-locked */
86dc4139
AM
28301+ warned = 0;
28302+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28303+ hbl = sbinfo->si_plink + i;
28304+ if (!warned && verbose && !hlist_bl_empty(hbl)) {
86dc4139
AM
28305+ pr_warn("pseudo-link is not flushed");
28306+ warned = 1;
28307+ }
8b6a4947 28308+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink)
5afbbe0d 28309+ iput(&icntnr->vfs_inode);
8b6a4947 28310+ INIT_HLIST_BL_HEAD(hbl);
86dc4139 28311+ }
1facf9fc 28312+}
28313+
e49829fe
JR
28314+void au_plink_clean(struct super_block *sb, int verbose)
28315+{
28316+ struct dentry *root;
28317+
28318+ root = sb->s_root;
28319+ aufs_write_lock(root);
28320+ if (au_opt_test(au_mntflags(sb), PLINK))
28321+ au_plink_put(sb, verbose);
28322+ aufs_write_unlock(root);
28323+}
28324+
86dc4139
AM
28325+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id)
28326+{
28327+ int do_put;
5afbbe0d 28328+ aufs_bindex_t btop, bbot, bindex;
86dc4139
AM
28329+
28330+ do_put = 0;
5afbbe0d
AM
28331+ btop = au_ibtop(inode);
28332+ bbot = au_ibbot(inode);
28333+ if (btop >= 0) {
28334+ for (bindex = btop; bindex <= bbot; bindex++) {
86dc4139
AM
28335+ if (!au_h_iptr(inode, bindex)
28336+ || au_ii_br_id(inode, bindex) != br_id)
28337+ continue;
28338+ au_set_h_iptr(inode, bindex, NULL, 0);
28339+ do_put = 1;
28340+ break;
28341+ }
28342+ if (do_put)
5afbbe0d 28343+ for (bindex = btop; bindex <= bbot; bindex++)
86dc4139
AM
28344+ if (au_h_iptr(inode, bindex)) {
28345+ do_put = 0;
28346+ break;
28347+ }
28348+ } else
28349+ do_put = 1;
28350+
28351+ return do_put;
28352+}
28353+
1facf9fc 28354+/* free the plinks on a branch specified by @br_id */
28355+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
28356+{
28357+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28358+ struct hlist_bl_head *hbl;
28359+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28360+ struct au_icntnr *icntnr;
1facf9fc 28361+ struct inode *inode;
86dc4139 28362+ int i, do_put;
1facf9fc 28363+
dece6358
AM
28364+ SiMustWriteLock(sb);
28365+
1facf9fc 28366+ sbinfo = au_sbi(sb);
28367+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28368+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28369+
8b6a4947 28370+ /* no bit_lock since sbinfo is write-locked */
86dc4139 28371+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28372+ hbl = sbinfo->si_plink + i;
28373+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) {
5afbbe0d 28374+ inode = au_igrab(&icntnr->vfs_inode);
86dc4139
AM
28375+ ii_write_lock_child(inode);
28376+ do_put = au_plink_do_half_refresh(inode, br_id);
5afbbe0d 28377+ if (do_put) {
8b6a4947 28378+ hlist_bl_del(&icntnr->plink);
5afbbe0d
AM
28379+ iput(inode);
28380+ }
86dc4139
AM
28381+ ii_write_unlock(inode);
28382+ iput(inode);
dece6358 28383+ }
dece6358
AM
28384+ }
28385+}
7f207e10 28386diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
fbc438ed
JR
28387--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 08:00:00.000000000 +0800
28388+++ linux/fs/aufs/poll.c 2019-07-11 21:21:54.382384486 +0800
cd7a4cd9
AM
28389@@ -0,0 +1,51 @@
28390+// SPDX-License-Identifier: GPL-2.0
dece6358 28391+/*
ba1aed25 28392+ * Copyright (C) 2005-2019 Junjiro R. Okajima
dece6358
AM
28393+ *
28394+ * This program, aufs is free software; you can redistribute it and/or modify
28395+ * it under the terms of the GNU General Public License as published by
28396+ * the Free Software Foundation; either version 2 of the License, or
28397+ * (at your option) any later version.
28398+ *
28399+ * This program is distributed in the hope that it will be useful,
28400+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28401+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28402+ * GNU General Public License for more details.
28403+ *
28404+ * You should have received a copy of the GNU General Public License
523b37e3 28405+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358
AM
28406+ */
28407+
1308ab2a 28408+/*
28409+ * poll operation
28410+ * There is only one filesystem which implements ->poll operation, currently.
28411+ */
28412+
28413+#include "aufs.h"
28414+
cd7a4cd9 28415+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt)
1308ab2a 28416+{
be118d29 28417+ __poll_t mask;
1308ab2a 28418+ struct file *h_file;
1308ab2a 28419+ struct super_block *sb;
28420+
28421+ /* We should pretend an error happened. */
be118d29 28422+ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */;
b912730e 28423+ sb = file->f_path.dentry->d_sb;
e49829fe 28424+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 28425+
521ced18 28426+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
062440b3
AM
28427+ if (IS_ERR(h_file)) {
28428+ AuDbg("h_file %ld\n", PTR_ERR(h_file));
1308ab2a 28429+ goto out;
062440b3 28430+ }
1308ab2a 28431+
cd7a4cd9 28432+ mask = vfs_poll(h_file, pt);
b912730e 28433+ fput(h_file); /* instead of au_read_post() */
1308ab2a 28434+
4f0767ce 28435+out:
1308ab2a 28436+ si_read_unlock(sb);
062440b3 28437+ if (mask & EPOLLERR)
b00004a5 28438+ AuDbg("mask 0x%x\n", mask);
1308ab2a 28439+ return mask;
28440+}
c1595e42 28441diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c
fbc438ed
JR
28442--- /usr/share/empty/fs/aufs/posix_acl.c 1970-01-01 08:00:00.000000000 +0800
28443+++ linux/fs/aufs/posix_acl.c 2019-07-11 21:21:54.382384486 +0800
062440b3 28444@@ -0,0 +1,103 @@
cd7a4cd9 28445+// SPDX-License-Identifier: GPL-2.0
c1595e42 28446+/*
ba1aed25 28447+ * Copyright (C) 2014-2019 Junjiro R. Okajima
c1595e42
JR
28448+ *
28449+ * This program, aufs is free software; you can redistribute it and/or modify
28450+ * it under the terms of the GNU General Public License as published by
28451+ * the Free Software Foundation; either version 2 of the License, or
28452+ * (at your option) any later version.
28453+ *
28454+ * This program is distributed in the hope that it will be useful,
28455+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28456+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28457+ * GNU General Public License for more details.
28458+ *
28459+ * You should have received a copy of the GNU General Public License
28460+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
28461+ */
28462+
28463+/*
28464+ * posix acl operations
28465+ */
28466+
28467+#include <linux/fs.h>
c1595e42
JR
28468+#include "aufs.h"
28469+
28470+struct posix_acl *aufs_get_acl(struct inode *inode, int type)
28471+{
28472+ struct posix_acl *acl;
28473+ int err;
28474+ aufs_bindex_t bindex;
28475+ struct inode *h_inode;
28476+ struct super_block *sb;
28477+
28478+ acl = NULL;
28479+ sb = inode->i_sb;
28480+ si_read_lock(sb, AuLock_FLUSH);
28481+ ii_read_lock_child(inode);
2121bcd9 28482+ if (!(sb->s_flags & SB_POSIXACL))
c1595e42
JR
28483+ goto out;
28484+
5afbbe0d 28485+ bindex = au_ibtop(inode);
c1595e42
JR
28486+ h_inode = au_h_iptr(inode, bindex);
28487+ if (unlikely(!h_inode
28488+ || ((h_inode->i_mode & S_IFMT)
28489+ != (inode->i_mode & S_IFMT)))) {
28490+ err = au_busy_or_stale();
28491+ acl = ERR_PTR(err);
28492+ goto out;
28493+ }
28494+
28495+ /* always topmost only */
28496+ acl = get_acl(h_inode, type);
a2654f78
AM
28497+ if (!IS_ERR_OR_NULL(acl))
28498+ set_cached_acl(inode, type, acl);
c1595e42
JR
28499+
28500+out:
28501+ ii_read_unlock(inode);
28502+ si_read_unlock(sb);
28503+
28504+ AuTraceErrPtr(acl);
28505+ return acl;
28506+}
28507+
28508+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
28509+{
28510+ int err;
28511+ ssize_t ssz;
28512+ struct dentry *dentry;
f2c43d5f 28513+ struct au_sxattr arg = {
c1595e42
JR
28514+ .type = AU_ACL_SET,
28515+ .u.acl_set = {
28516+ .acl = acl,
28517+ .type = type
28518+ },
28519+ };
28520+
5afbbe0d
AM
28521+ IMustLock(inode);
28522+
c1595e42
JR
28523+ if (inode->i_ino == AUFS_ROOT_INO)
28524+ dentry = dget(inode->i_sb->s_root);
28525+ else {
28526+ dentry = d_find_alias(inode);
28527+ if (!dentry)
28528+ dentry = d_find_any_alias(inode);
28529+ if (!dentry) {
28530+ pr_warn("cannot handle this inode, "
28531+ "please report to aufs-users ML\n");
28532+ err = -ENOENT;
28533+ goto out;
28534+ }
28535+ }
28536+
f2c43d5f 28537+ ssz = au_sxattr(dentry, inode, &arg);
c1595e42
JR
28538+ dput(dentry);
28539+ err = ssz;
a2654f78 28540+ if (ssz >= 0) {
c1595e42 28541+ err = 0;
a2654f78
AM
28542+ set_cached_acl(inode, type, acl);
28543+ }
c1595e42
JR
28544+
28545+out:
c1595e42
JR
28546+ return err;
28547+}
7f207e10 28548diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
fbc438ed
JR
28549--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 08:00:00.000000000 +0800
28550+++ linux/fs/aufs/procfs.c 2019-07-11 21:21:54.382384486 +0800
062440b3 28551@@ -0,0 +1,171 @@
cd7a4cd9 28552+// SPDX-License-Identifier: GPL-2.0
e49829fe 28553+/*
ba1aed25 28554+ * Copyright (C) 2010-2019 Junjiro R. Okajima
e49829fe
JR
28555+ *
28556+ * This program, aufs is free software; you can redistribute it and/or modify
28557+ * it under the terms of the GNU General Public License as published by
28558+ * the Free Software Foundation; either version 2 of the License, or
28559+ * (at your option) any later version.
28560+ *
28561+ * This program is distributed in the hope that it will be useful,
28562+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28563+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28564+ * GNU General Public License for more details.
28565+ *
28566+ * You should have received a copy of the GNU General Public License
523b37e3 28567+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
28568+ */
28569+
28570+/*
28571+ * procfs interfaces
28572+ */
28573+
28574+#include <linux/proc_fs.h>
28575+#include "aufs.h"
28576+
28577+static int au_procfs_plm_release(struct inode *inode, struct file *file)
28578+{
28579+ struct au_sbinfo *sbinfo;
28580+
28581+ sbinfo = file->private_data;
28582+ if (sbinfo) {
28583+ au_plink_maint_leave(sbinfo);
28584+ kobject_put(&sbinfo->si_kobj);
28585+ }
28586+
28587+ return 0;
28588+}
28589+
28590+static void au_procfs_plm_write_clean(struct file *file)
28591+{
28592+ struct au_sbinfo *sbinfo;
28593+
28594+ sbinfo = file->private_data;
28595+ if (sbinfo)
28596+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
28597+}
28598+
28599+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
28600+{
28601+ int err;
28602+ struct super_block *sb;
28603+ struct au_sbinfo *sbinfo;
8b6a4947 28604+ struct hlist_bl_node *pos;
e49829fe
JR
28605+
28606+ err = -EBUSY;
28607+ if (unlikely(file->private_data))
28608+ goto out;
28609+
28610+ sb = NULL;
53392da6 28611+ /* don't use au_sbilist_lock() here */
8b6a4947
AM
28612+ hlist_bl_lock(&au_sbilist);
28613+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
e49829fe 28614+ if (id == sysaufs_si_id(sbinfo)) {
83b672a5
AM
28615+ if (kobject_get_unless_zero(&sbinfo->si_kobj))
28616+ sb = sbinfo->si_sb;
e49829fe
JR
28617+ break;
28618+ }
8b6a4947 28619+ hlist_bl_unlock(&au_sbilist);
e49829fe
JR
28620+
28621+ err = -EINVAL;
28622+ if (unlikely(!sb))
28623+ goto out;
28624+
28625+ err = au_plink_maint_enter(sb);
28626+ if (!err)
28627+ /* keep kobject_get() */
28628+ file->private_data = sbinfo;
28629+ else
28630+ kobject_put(&sbinfo->si_kobj);
28631+out:
28632+ return err;
28633+}
28634+
28635+/*
28636+ * Accept a valid "si=xxxx" only.
28637+ * Once it is accepted successfully, accept "clean" too.
28638+ */
28639+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
28640+ size_t count, loff_t *ppos)
28641+{
28642+ ssize_t err;
28643+ unsigned long id;
28644+ /* last newline is allowed */
28645+ char buf[3 + sizeof(unsigned long) * 2 + 1];
28646+
28647+ err = -EACCES;
28648+ if (unlikely(!capable(CAP_SYS_ADMIN)))
28649+ goto out;
28650+
28651+ err = -EINVAL;
28652+ if (unlikely(count > sizeof(buf)))
28653+ goto out;
28654+
28655+ err = copy_from_user(buf, ubuf, count);
28656+ if (unlikely(err)) {
28657+ err = -EFAULT;
28658+ goto out;
28659+ }
28660+ buf[count] = 0;
28661+
28662+ err = -EINVAL;
28663+ if (!strcmp("clean", buf)) {
28664+ au_procfs_plm_write_clean(file);
28665+ goto out_success;
28666+ } else if (unlikely(strncmp("si=", buf, 3)))
28667+ goto out;
28668+
9dbd164d 28669+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
28670+ if (unlikely(err))
28671+ goto out;
28672+
28673+ err = au_procfs_plm_write_si(file, id);
28674+ if (unlikely(err))
28675+ goto out;
28676+
28677+out_success:
28678+ err = count; /* success */
28679+out:
28680+ return err;
28681+}
28682+
28683+static const struct file_operations au_procfs_plm_fop = {
28684+ .write = au_procfs_plm_write,
28685+ .release = au_procfs_plm_release,
28686+ .owner = THIS_MODULE
28687+};
28688+
28689+/* ---------------------------------------------------------------------- */
28690+
28691+static struct proc_dir_entry *au_procfs_dir;
28692+
28693+void au_procfs_fin(void)
28694+{
28695+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
28696+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28697+}
28698+
28699+int __init au_procfs_init(void)
28700+{
28701+ int err;
28702+ struct proc_dir_entry *entry;
28703+
28704+ err = -ENOMEM;
28705+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
28706+ if (unlikely(!au_procfs_dir))
28707+ goto out;
28708+
cd7a4cd9 28709+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200,
e49829fe
JR
28710+ au_procfs_dir, &au_procfs_plm_fop);
28711+ if (unlikely(!entry))
28712+ goto out_dir;
28713+
28714+ err = 0;
28715+ goto out; /* success */
28716+
28717+
28718+out_dir:
28719+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28720+out:
28721+ return err;
28722+}
7f207e10 28723diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
fbc438ed
JR
28724--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 08:00:00.000000000 +0800
28725+++ linux/fs/aufs/rdu.c 2019-07-11 21:21:54.382384486 +0800
ba1aed25 28726@@ -0,0 +1,384 @@
cd7a4cd9 28727+// SPDX-License-Identifier: GPL-2.0
1308ab2a 28728+/*
ba1aed25 28729+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1308ab2a 28730+ *
28731+ * This program, aufs is free software; you can redistribute it and/or modify
28732+ * it under the terms of the GNU General Public License as published by
28733+ * the Free Software Foundation; either version 2 of the License, or
28734+ * (at your option) any later version.
28735+ *
28736+ * This program is distributed in the hope that it will be useful,
28737+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28738+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28739+ * GNU General Public License for more details.
28740+ *
28741+ * You should have received a copy of the GNU General Public License
523b37e3 28742+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1308ab2a 28743+ */
28744+
28745+/*
28746+ * readdir in userspace.
28747+ */
28748+
b752ccd1 28749+#include <linux/compat.h>
4a4d8108 28750+#include <linux/fs_stack.h>
1308ab2a 28751+#include <linux/security.h>
1308ab2a 28752+#include "aufs.h"
28753+
28754+/* bits for struct aufs_rdu.flags */
28755+#define AuRdu_CALLED 1
28756+#define AuRdu_CONT (1 << 1)
28757+#define AuRdu_FULL (1 << 2)
28758+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
28759+#define au_fset_rdu(flags, name) \
28760+ do { (flags) |= AuRdu_##name; } while (0)
28761+#define au_fclr_rdu(flags, name) \
28762+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 28763+
28764+struct au_rdu_arg {
392086de 28765+ struct dir_context ctx;
1308ab2a 28766+ struct aufs_rdu *rdu;
28767+ union au_rdu_ent_ul ent;
28768+ unsigned long end;
28769+
28770+ struct super_block *sb;
28771+ int err;
28772+};
28773+
392086de 28774+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen,
1308ab2a 28775+ loff_t offset, u64 h_ino, unsigned int d_type)
28776+{
28777+ int err, len;
392086de 28778+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx);
1308ab2a 28779+ struct aufs_rdu *rdu = arg->rdu;
28780+ struct au_rdu_ent ent;
28781+
28782+ err = 0;
28783+ arg->err = 0;
28784+ au_fset_rdu(rdu->cookie.flags, CALLED);
28785+ len = au_rdu_len(nlen);
28786+ if (arg->ent.ul + len < arg->end) {
28787+ ent.ino = h_ino;
28788+ ent.bindex = rdu->cookie.bindex;
28789+ ent.type = d_type;
28790+ ent.nlen = nlen;
4a4d8108
AM
28791+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
28792+ ent.type = DT_UNKNOWN;
1308ab2a 28793+
9dbd164d 28794+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28795+ err = -EFAULT;
28796+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
28797+ goto out;
28798+ if (copy_to_user(arg->ent.e->name, name, nlen))
28799+ goto out;
28800+ /* the terminating NULL */
28801+ if (__put_user(0, arg->ent.e->name + nlen))
28802+ goto out;
28803+ err = 0;
28804+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
28805+ arg->ent.ul += len;
28806+ rdu->rent++;
28807+ } else {
28808+ err = -EFAULT;
28809+ au_fset_rdu(rdu->cookie.flags, FULL);
28810+ rdu->full = 1;
28811+ rdu->tail = arg->ent;
28812+ }
28813+
4f0767ce 28814+out:
1308ab2a 28815+ /* AuTraceErr(err); */
28816+ return err;
28817+}
28818+
28819+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
28820+{
28821+ int err;
28822+ loff_t offset;
28823+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
28824+
92d182d2 28825+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 28826+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
28827+ err = offset;
28828+ if (unlikely(offset != cookie->h_pos))
28829+ goto out;
28830+
28831+ err = 0;
28832+ do {
28833+ arg->err = 0;
28834+ au_fclr_rdu(cookie->flags, CALLED);
28835+ /* smp_mb(); */
392086de 28836+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1308ab2a 28837+ if (err >= 0)
28838+ err = arg->err;
28839+ } while (!err
28840+ && au_ftest_rdu(cookie->flags, CALLED)
28841+ && !au_ftest_rdu(cookie->flags, FULL));
28842+ cookie->h_pos = h_file->f_pos;
28843+
4f0767ce 28844+out:
1308ab2a 28845+ AuTraceErr(err);
28846+ return err;
28847+}
28848+
28849+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
28850+{
28851+ int err;
5afbbe0d 28852+ aufs_bindex_t bbot;
392086de
AM
28853+ struct au_rdu_arg arg = {
28854+ .ctx = {
2000de60 28855+ .actor = au_rdu_fill
392086de
AM
28856+ }
28857+ };
1308ab2a 28858+ struct dentry *dentry;
28859+ struct inode *inode;
28860+ struct file *h_file;
28861+ struct au_rdu_cookie *cookie = &rdu->cookie;
28862+
ba1aed25
AM
28863+ /* VERIFY_WRITE */
28864+ err = !access_ok(rdu->ent.e, rdu->sz);
1308ab2a 28865+ if (unlikely(err)) {
28866+ err = -EFAULT;
28867+ AuTraceErr(err);
28868+ goto out;
28869+ }
28870+ rdu->rent = 0;
28871+ rdu->tail = rdu->ent;
28872+ rdu->full = 0;
28873+ arg.rdu = rdu;
28874+ arg.ent = rdu->ent;
28875+ arg.end = arg.ent.ul;
28876+ arg.end += rdu->sz;
28877+
28878+ err = -ENOTDIR;
5afbbe0d 28879+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared))
1308ab2a 28880+ goto out;
28881+
28882+ err = security_file_permission(file, MAY_READ);
28883+ AuTraceErr(err);
28884+ if (unlikely(err))
28885+ goto out;
28886+
2000de60 28887+ dentry = file->f_path.dentry;
5527c038 28888+ inode = d_inode(dentry);
5afbbe0d 28889+ inode_lock_shared(inode);
1308ab2a 28890+
28891+ arg.sb = inode->i_sb;
e49829fe
JR
28892+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
28893+ if (unlikely(err))
28894+ goto out_mtx;
027c5e7a
AM
28895+ err = au_alive_dir(dentry);
28896+ if (unlikely(err))
28897+ goto out_si;
e49829fe 28898+ /* todo: reval? */
1308ab2a 28899+ fi_read_lock(file);
28900+
28901+ err = -EAGAIN;
28902+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
28903+ && cookie->generation != au_figen(file)))
28904+ goto out_unlock;
28905+
28906+ err = 0;
28907+ if (!rdu->blk) {
28908+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
28909+ if (!rdu->blk)
28910+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
28911+ }
5afbbe0d
AM
28912+ bbot = au_fbtop(file);
28913+ if (cookie->bindex < bbot)
28914+ cookie->bindex = bbot;
28915+ bbot = au_fbbot_dir(file);
28916+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */
28917+ for (; !err && cookie->bindex <= bbot;
1308ab2a 28918+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 28919+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 28920+ if (!h_file)
28921+ continue;
28922+
28923+ au_fclr_rdu(cookie->flags, FULL);
28924+ err = au_rdu_do(h_file, &arg);
28925+ AuTraceErr(err);
28926+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
28927+ break;
28928+ }
28929+ AuDbg("rent %llu\n", rdu->rent);
28930+
28931+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
28932+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
28933+ au_fset_rdu(cookie->flags, CONT);
28934+ cookie->generation = au_figen(file);
28935+ }
28936+
28937+ ii_read_lock_child(inode);
5afbbe0d 28938+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode)));
1308ab2a 28939+ ii_read_unlock(inode);
28940+
4f0767ce 28941+out_unlock:
1308ab2a 28942+ fi_read_unlock(file);
027c5e7a 28943+out_si:
1308ab2a 28944+ si_read_unlock(arg.sb);
4f0767ce 28945+out_mtx:
5afbbe0d 28946+ inode_unlock_shared(inode);
4f0767ce 28947+out:
1308ab2a 28948+ AuTraceErr(err);
28949+ return err;
28950+}
28951+
28952+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
28953+{
28954+ int err;
28955+ ino_t ino;
28956+ unsigned long long nent;
28957+ union au_rdu_ent_ul *u;
28958+ struct au_rdu_ent ent;
28959+ struct super_block *sb;
28960+
28961+ err = 0;
28962+ nent = rdu->nent;
28963+ u = &rdu->ent;
2000de60 28964+ sb = file->f_path.dentry->d_sb;
1308ab2a 28965+ si_read_lock(sb, AuLock_FLUSH);
28966+ while (nent-- > 0) {
9dbd164d 28967+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28968+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108 28969+ if (!err)
ba1aed25
AM
28970+ /* VERIFY_WRITE */
28971+ err = !access_ok(&u->e->ino, sizeof(ino));
1308ab2a 28972+ if (unlikely(err)) {
28973+ err = -EFAULT;
28974+ AuTraceErr(err);
28975+ break;
28976+ }
28977+
28978+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
28979+ if (!ent.wh)
28980+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
28981+ else
28982+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
28983+ &ino);
28984+ if (unlikely(err)) {
28985+ AuTraceErr(err);
28986+ break;
28987+ }
28988+
28989+ err = __put_user(ino, &u->e->ino);
28990+ if (unlikely(err)) {
28991+ err = -EFAULT;
28992+ AuTraceErr(err);
28993+ break;
28994+ }
28995+ u->ul += au_rdu_len(ent.nlen);
28996+ }
28997+ si_read_unlock(sb);
28998+
28999+ return err;
29000+}
29001+
29002+/* ---------------------------------------------------------------------- */
29003+
29004+static int au_rdu_verify(struct aufs_rdu *rdu)
29005+{
b752ccd1 29006+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 29007+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 29008+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 29009+ rdu->blk,
29010+ rdu->rent, rdu->shwh, rdu->full,
29011+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
29012+ rdu->cookie.generation);
dece6358 29013+
b752ccd1 29014+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 29015+ return 0;
dece6358 29016+
b752ccd1
AM
29017+ AuDbg("%u:%u\n",
29018+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 29019+ return -EINVAL;
29020+}
29021+
29022+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 29023+{
1308ab2a 29024+ long err, e;
29025+ struct aufs_rdu rdu;
29026+ void __user *p = (void __user *)arg;
dece6358 29027+
1308ab2a 29028+ err = copy_from_user(&rdu, p, sizeof(rdu));
29029+ if (unlikely(err)) {
29030+ err = -EFAULT;
29031+ AuTraceErr(err);
29032+ goto out;
29033+ }
29034+ err = au_rdu_verify(&rdu);
dece6358
AM
29035+ if (unlikely(err))
29036+ goto out;
29037+
1308ab2a 29038+ switch (cmd) {
29039+ case AUFS_CTL_RDU:
29040+ err = au_rdu(file, &rdu);
29041+ if (unlikely(err))
29042+ break;
dece6358 29043+
1308ab2a 29044+ e = copy_to_user(p, &rdu, sizeof(rdu));
29045+ if (unlikely(e)) {
29046+ err = -EFAULT;
29047+ AuTraceErr(err);
29048+ }
29049+ break;
29050+ case AUFS_CTL_RDU_INO:
29051+ err = au_rdu_ino(file, &rdu);
29052+ break;
29053+
29054+ default:
4a4d8108 29055+ /* err = -ENOTTY; */
1308ab2a 29056+ err = -EINVAL;
29057+ }
dece6358 29058+
4f0767ce 29059+out:
1308ab2a 29060+ AuTraceErr(err);
29061+ return err;
1facf9fc 29062+}
b752ccd1
AM
29063+
29064+#ifdef CONFIG_COMPAT
29065+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
29066+{
29067+ long err, e;
29068+ struct aufs_rdu rdu;
29069+ void __user *p = compat_ptr(arg);
29070+
29071+ /* todo: get_user()? */
29072+ err = copy_from_user(&rdu, p, sizeof(rdu));
29073+ if (unlikely(err)) {
29074+ err = -EFAULT;
29075+ AuTraceErr(err);
29076+ goto out;
29077+ }
29078+ rdu.ent.e = compat_ptr(rdu.ent.ul);
29079+ err = au_rdu_verify(&rdu);
29080+ if (unlikely(err))
29081+ goto out;
29082+
29083+ switch (cmd) {
29084+ case AUFS_CTL_RDU:
29085+ err = au_rdu(file, &rdu);
29086+ if (unlikely(err))
29087+ break;
29088+
29089+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
29090+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
29091+ e = copy_to_user(p, &rdu, sizeof(rdu));
29092+ if (unlikely(e)) {
29093+ err = -EFAULT;
29094+ AuTraceErr(err);
29095+ }
29096+ break;
29097+ case AUFS_CTL_RDU_INO:
29098+ err = au_rdu_ino(file, &rdu);
29099+ break;
29100+
29101+ default:
29102+ /* err = -ENOTTY; */
29103+ err = -EINVAL;
29104+ }
29105+
4f0767ce 29106+out:
b752ccd1
AM
29107+ AuTraceErr(err);
29108+ return err;
29109+}
29110+#endif
7f207e10 29111diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
fbc438ed
JR
29112--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 08:00:00.000000000 +0800
29113+++ linux/fs/aufs/rwsem.h 2019-07-11 21:21:54.382384486 +0800
062440b3
AM
29114@@ -0,0 +1,73 @@
29115+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 29116+/*
ba1aed25 29117+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 29118+ *
29119+ * This program, aufs is free software; you can redistribute it and/or modify
29120+ * it under the terms of the GNU General Public License as published by
29121+ * the Free Software Foundation; either version 2 of the License, or
29122+ * (at your option) any later version.
dece6358
AM
29123+ *
29124+ * This program is distributed in the hope that it will be useful,
29125+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29126+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29127+ * GNU General Public License for more details.
29128+ *
29129+ * You should have received a copy of the GNU General Public License
523b37e3 29130+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29131+ */
29132+
29133+/*
29134+ * simple read-write semaphore wrappers
29135+ */
29136+
29137+#ifndef __AUFS_RWSEM_H__
29138+#define __AUFS_RWSEM_H__
29139+
29140+#ifdef __KERNEL__
29141+
4a4d8108 29142+#include "debug.h"
dece6358 29143+
acd2b654 29144+/* in the future, the name 'au_rwsem' will be totally gone */
8b6a4947 29145+#define au_rwsem rw_semaphore
dece6358
AM
29146+
29147+/* to debug easier, do not make them inlined functions */
8b6a4947 29148+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw))
dece6358 29149+/* rwsem_is_locked() is unusable */
8b6a4947
AM
29150+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \
29151+ && debug_locks \
29152+ && !lockdep_is_held_type(rw, 1))
29153+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \
29154+ && debug_locks \
29155+ && !lockdep_is_held_type(rw, 0))
29156+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \
29157+ && debug_locks \
29158+ && !lockdep_is_held(rw))
29159+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \
29160+ && debug_locks \
29161+ && lockdep_is_held(rw))
29162+
29163+#define au_rw_init(rw) init_rwsem(rw)
dece6358 29164+
5afbbe0d
AM
29165+#define au_rw_init_wlock(rw) do { \
29166+ au_rw_init(rw); \
8b6a4947 29167+ down_write(rw); \
5afbbe0d 29168+ } while (0)
dece6358 29169+
8b6a4947
AM
29170+#define au_rw_init_wlock_nested(rw, lsc) do { \
29171+ au_rw_init(rw); \
29172+ down_write_nested(rw, lsc); \
5afbbe0d 29173+ } while (0)
dece6358 29174+
8b6a4947
AM
29175+#define au_rw_read_lock(rw) down_read(rw)
29176+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc)
29177+#define au_rw_read_unlock(rw) up_read(rw)
29178+#define au_rw_dgrade_lock(rw) downgrade_write(rw)
29179+#define au_rw_write_lock(rw) down_write(rw)
29180+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc)
29181+#define au_rw_write_unlock(rw) up_write(rw)
29182+/* why is not _nested version defined? */
29183+#define au_rw_read_trylock(rw) down_read_trylock(rw)
29184+#define au_rw_write_trylock(rw) down_write_trylock(rw)
1facf9fc 29185+
29186+#endif /* __KERNEL__ */
29187+#endif /* __AUFS_RWSEM_H__ */
7f207e10 29188diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
fbc438ed
JR
29189--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 08:00:00.000000000 +0800
29190+++ linux/fs/aufs/sbinfo.c 2019-07-11 21:21:54.382384486 +0800
eca801bf 29191@@ -0,0 +1,314 @@
cd7a4cd9 29192+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29193+/*
ba1aed25 29194+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 29195+ *
29196+ * This program, aufs is free software; you can redistribute it and/or modify
29197+ * it under the terms of the GNU General Public License as published by
29198+ * the Free Software Foundation; either version 2 of the License, or
29199+ * (at your option) any later version.
dece6358
AM
29200+ *
29201+ * This program is distributed in the hope that it will be useful,
29202+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29203+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29204+ * GNU General Public License for more details.
29205+ *
29206+ * You should have received a copy of the GNU General Public License
523b37e3 29207+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29208+ */
29209+
29210+/*
29211+ * superblock private data
29212+ */
29213+
eca801bf 29214+#include <linux/iversion.h>
1facf9fc 29215+#include "aufs.h"
29216+
29217+/*
29218+ * they are necessary regardless sysfs is disabled.
29219+ */
29220+void au_si_free(struct kobject *kobj)
29221+{
86dc4139 29222+ int i;
1facf9fc 29223+ struct au_sbinfo *sbinfo;
b752ccd1 29224+ char *locked __maybe_unused; /* debug only */
1facf9fc 29225+
29226+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
86dc4139 29227+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29228+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i));
f0c0a007 29229+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
5afbbe0d 29230+
acd2b654
AM
29231+ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0));
29232+ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0);
29233+ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0));
29234+ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0);
1facf9fc 29235+
062440b3 29236+ dbgaufs_si_fin(sbinfo);
e49829fe 29237+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 29238+ au_br_free(sbinfo);
e49829fe 29239+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1 29240+
9f237c51 29241+ au_kfree_try_rcu(sbinfo->si_branch);
1facf9fc 29242+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 29243+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 29244+
acd2b654
AM
29245+ au_lcnt_wait_for_fin(&sbinfo->si_ninodes);
29246+ /* si_nfiles is waited too */
9f237c51 29247+ au_kfree_rcu(sbinfo);
1facf9fc 29248+}
29249+
29250+int au_si_alloc(struct super_block *sb)
29251+{
86dc4139 29252+ int err, i;
1facf9fc 29253+ struct au_sbinfo *sbinfo;
29254+
29255+ err = -ENOMEM;
4a4d8108 29256+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 29257+ if (unlikely(!sbinfo))
29258+ goto out;
29259+
29260+ /* will be reallocated separately */
29261+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
29262+ if (unlikely(!sbinfo->si_branch))
febd17d6 29263+ goto out_sbinfo;
1facf9fc 29264+
1facf9fc 29265+ err = sysaufs_si_init(sbinfo);
062440b3
AM
29266+ if (!err) {
29267+ dbgaufs_si_null(sbinfo);
29268+ err = dbgaufs_si_init(sbinfo);
29269+ if (unlikely(err))
29270+ kobject_put(&sbinfo->si_kobj);
29271+ }
1facf9fc 29272+ if (unlikely(err))
29273+ goto out_br;
29274+
29275+ au_nwt_init(&sbinfo->si_nowait);
dece6358 29276+ au_rw_init_wlock(&sbinfo->si_rwsem);
b752ccd1 29277+
acd2b654
AM
29278+ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL);
29279+ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL);
7f207e10 29280+
5afbbe0d 29281+ sbinfo->si_bbot = -1;
392086de 29282+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2;
1facf9fc 29283+
29284+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
29285+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
29286+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
29287+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 29288+
076b876e
AM
29289+ au_fhsm_init(sbinfo);
29290+
e49829fe 29291+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 29292+
392086de
AM
29293+ sbinfo->si_xino_jiffy = jiffies;
29294+ sbinfo->si_xino_expire
29295+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC);
1facf9fc 29296+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 29297+ /* leave si_xib_last_pindex and si_xib_next_bit */
29298+
8b6a4947 29299+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen);
b912730e 29300+
e49829fe 29301+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 29302+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
29303+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
29304+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
29305+
86dc4139 29306+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29307+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i);
1facf9fc 29308+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 29309+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 29310+
8b6a4947 29311+ INIT_HLIST_BL_HEAD(&sbinfo->si_files);
523b37e3 29312+
b95c5147
AM
29313+ /* with getattr by default */
29314+ sbinfo->si_iop_array = aufs_iop;
29315+
1facf9fc 29316+ /* leave other members for sysaufs and si_mnt. */
29317+ sbinfo->si_sb = sb;
29318+ sb->s_fs_info = sbinfo;
b752ccd1 29319+ si_pid_set(sb);
1facf9fc 29320+ return 0; /* success */
29321+
4f0767ce 29322+out_br:
9f237c51 29323+ au_kfree_try_rcu(sbinfo->si_branch);
4f0767ce 29324+out_sbinfo:
9f237c51 29325+ au_kfree_rcu(sbinfo);
4f0767ce 29326+out:
1facf9fc 29327+ return err;
29328+}
29329+
e2f27e51 29330+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
1facf9fc 29331+{
29332+ int err, sz;
29333+ struct au_branch **brp;
29334+
dece6358
AM
29335+ AuRwMustWriteLock(&sbinfo->si_rwsem);
29336+
1facf9fc 29337+ err = -ENOMEM;
5afbbe0d 29338+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1);
1facf9fc 29339+ if (unlikely(!sz))
29340+ sz = sizeof(*brp);
e2f27e51
AM
29341+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS,
29342+ may_shrink);
1facf9fc 29343+ if (brp) {
29344+ sbinfo->si_branch = brp;
29345+ err = 0;
29346+ }
29347+
29348+ return err;
29349+}
29350+
29351+/* ---------------------------------------------------------------------- */
29352+
29353+unsigned int au_sigen_inc(struct super_block *sb)
29354+{
29355+ unsigned int gen;
5527c038 29356+ struct inode *inode;
1facf9fc 29357+
dece6358
AM
29358+ SiMustWriteLock(sb);
29359+
1facf9fc 29360+ gen = ++au_sbi(sb)->si_generation;
29361+ au_update_digen(sb->s_root);
5527c038
JR
29362+ inode = d_inode(sb->s_root);
29363+ au_update_iigen(inode, /*half*/0);
be118d29 29364+ inode_inc_iversion(inode);
1facf9fc 29365+ return gen;
29366+}
29367+
29368+aufs_bindex_t au_new_br_id(struct super_block *sb)
29369+{
29370+ aufs_bindex_t br_id;
29371+ int i;
29372+ struct au_sbinfo *sbinfo;
29373+
dece6358
AM
29374+ SiMustWriteLock(sb);
29375+
1facf9fc 29376+ sbinfo = au_sbi(sb);
29377+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
29378+ br_id = ++sbinfo->si_last_br_id;
7f207e10 29379+ AuDebugOn(br_id < 0);
1facf9fc 29380+ if (br_id && au_br_index(sb, br_id) < 0)
29381+ return br_id;
29382+ }
29383+
29384+ return -1;
29385+}
29386+
29387+/* ---------------------------------------------------------------------- */
29388+
e49829fe
JR
29389+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
29390+int si_read_lock(struct super_block *sb, int flags)
29391+{
29392+ int err;
29393+
29394+ err = 0;
29395+ if (au_ftest_lock(flags, FLUSH))
29396+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29397+
29398+ si_noflush_read_lock(sb);
29399+ err = au_plink_maint(sb, flags);
29400+ if (unlikely(err))
29401+ si_read_unlock(sb);
29402+
29403+ return err;
29404+}
29405+
29406+int si_write_lock(struct super_block *sb, int flags)
29407+{
29408+ int err;
29409+
29410+ if (au_ftest_lock(flags, FLUSH))
29411+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29412+
29413+ si_noflush_write_lock(sb);
29414+ err = au_plink_maint(sb, flags);
29415+ if (unlikely(err))
29416+ si_write_unlock(sb);
29417+
29418+ return err;
29419+}
29420+
1facf9fc 29421+/* dentry and super_block lock. call at entry point */
e49829fe 29422+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 29423+{
e49829fe 29424+ int err;
027c5e7a 29425+ struct super_block *sb;
e49829fe 29426+
027c5e7a
AM
29427+ sb = dentry->d_sb;
29428+ err = si_read_lock(sb, flags);
29429+ if (unlikely(err))
29430+ goto out;
29431+
29432+ if (au_ftest_lock(flags, DW))
29433+ di_write_lock_child(dentry);
29434+ else
29435+ di_read_lock_child(dentry, flags);
29436+
29437+ if (au_ftest_lock(flags, GEN)) {
29438+ err = au_digen_test(dentry, au_sigen(sb));
79b8bda9
AM
29439+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE))
29440+ AuDebugOn(!err && au_dbrange_test(dentry));
29441+ else if (!err)
29442+ err = au_dbrange_test(dentry);
027c5e7a
AM
29443+ if (unlikely(err))
29444+ aufs_read_unlock(dentry, flags);
e49829fe
JR
29445+ }
29446+
027c5e7a 29447+out:
e49829fe 29448+ return err;
1facf9fc 29449+}
29450+
29451+void aufs_read_unlock(struct dentry *dentry, int flags)
29452+{
29453+ if (au_ftest_lock(flags, DW))
29454+ di_write_unlock(dentry);
29455+ else
29456+ di_read_unlock(dentry, flags);
29457+ si_read_unlock(dentry->d_sb);
29458+}
29459+
29460+void aufs_write_lock(struct dentry *dentry)
29461+{
e49829fe 29462+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 29463+ di_write_lock_child(dentry);
29464+}
29465+
29466+void aufs_write_unlock(struct dentry *dentry)
29467+{
29468+ di_write_unlock(dentry);
29469+ si_write_unlock(dentry->d_sb);
29470+}
29471+
e49829fe 29472+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 29473+{
e49829fe 29474+ int err;
027c5e7a
AM
29475+ unsigned int sigen;
29476+ struct super_block *sb;
e49829fe 29477+
027c5e7a
AM
29478+ sb = d1->d_sb;
29479+ err = si_read_lock(sb, flags);
29480+ if (unlikely(err))
29481+ goto out;
29482+
b95c5147 29483+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS));
027c5e7a
AM
29484+
29485+ if (au_ftest_lock(flags, GEN)) {
29486+ sigen = au_sigen(sb);
29487+ err = au_digen_test(d1, sigen);
29488+ AuDebugOn(!err && au_dbrange_test(d1));
29489+ if (!err) {
29490+ err = au_digen_test(d2, sigen);
29491+ AuDebugOn(!err && au_dbrange_test(d2));
29492+ }
29493+ if (unlikely(err))
29494+ aufs_read_and_write_unlock2(d1, d2);
29495+ }
29496+
29497+out:
e49829fe 29498+ return err;
1facf9fc 29499+}
29500+
29501+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
29502+{
29503+ di_write_unlock2(d1, d2);
29504+ si_read_unlock(d1->d_sb);
29505+}
7f207e10 29506diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
fbc438ed
JR
29507--- /usr/share/empty/fs/aufs/super.c 1970-01-01 08:00:00.000000000 +0800
29508+++ linux/fs/aufs/super.c 2019-07-11 21:21:54.382384486 +0800
29509@@ -0,0 +1,1047 @@
cd7a4cd9 29510+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29511+/*
ba1aed25 29512+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 29513+ *
29514+ * This program, aufs is free software; you can redistribute it and/or modify
29515+ * it under the terms of the GNU General Public License as published by
29516+ * the Free Software Foundation; either version 2 of the License, or
29517+ * (at your option) any later version.
dece6358
AM
29518+ *
29519+ * This program is distributed in the hope that it will be useful,
29520+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29521+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29522+ * GNU General Public License for more details.
29523+ *
29524+ * You should have received a copy of the GNU General Public License
523b37e3 29525+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29526+ */
29527+
29528+/*
29529+ * mount and super_block operations
29530+ */
29531+
eca801bf 29532+#include <linux/iversion.h>
f6c5ef8b 29533+#include <linux/mm.h>
1facf9fc 29534+#include <linux/seq_file.h>
29535+#include <linux/statfs.h>
7f207e10 29536+#include <linux/vmalloc.h>
1facf9fc 29537+#include "aufs.h"
29538+
29539+/*
29540+ * super_operations
29541+ */
29542+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
29543+{
29544+ struct au_icntnr *c;
29545+
29546+ c = au_cache_alloc_icntnr();
29547+ if (c) {
027c5e7a 29548+ au_icntnr_init(c);
be118d29 29549+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */
1facf9fc 29550+ c->iinfo.ii_hinode = NULL;
29551+ return &c->vfs_inode;
29552+ }
29553+ return NULL;
29554+}
29555+
29556+static void aufs_destroy_inode(struct inode *inode)
29557+{
5afbbe0d
AM
29558+ if (!au_is_bad_inode(inode))
29559+ au_iinfo_fin(inode);
fbc438ed
JR
29560+}
29561+
29562+static void aufs_free_inode(struct inode *inode)
29563+{
29564+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
1facf9fc 29565+}
29566+
29567+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
29568+{
29569+ struct inode *inode;
29570+ int err;
29571+
29572+ inode = iget_locked(sb, ino);
29573+ if (unlikely(!inode)) {
29574+ inode = ERR_PTR(-ENOMEM);
29575+ goto out;
29576+ }
29577+ if (!(inode->i_state & I_NEW))
29578+ goto out;
29579+
29580+ err = au_xigen_new(inode);
29581+ if (!err)
29582+ err = au_iinfo_init(inode);
29583+ if (!err)
be118d29 29584+ inode_inc_iversion(inode);
1facf9fc 29585+ else {
29586+ iget_failed(inode);
29587+ inode = ERR_PTR(err);
29588+ }
29589+
4f0767ce 29590+out:
1facf9fc 29591+ /* never return NULL */
29592+ AuDebugOn(!inode);
29593+ AuTraceErrPtr(inode);
29594+ return inode;
29595+}
29596+
29597+/* lock free root dinfo */
29598+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
29599+{
29600+ int err;
5afbbe0d 29601+ aufs_bindex_t bindex, bbot;
1facf9fc 29602+ struct path path;
4a4d8108 29603+ struct au_hdentry *hdp;
1facf9fc 29604+ struct au_branch *br;
076b876e 29605+ au_br_perm_str_t perm;
1facf9fc 29606+
29607+ err = 0;
5afbbe0d
AM
29608+ bbot = au_sbbot(sb);
29609+ bindex = 0;
29610+ hdp = au_hdentry(au_di(sb->s_root), bindex);
29611+ for (; !err && bindex <= bbot; bindex++, hdp++) {
1facf9fc 29612+ br = au_sbr(sb, bindex);
86dc4139 29613+ path.mnt = au_br_mnt(br);
5afbbe0d 29614+ path.dentry = hdp->hd_dentry;
1facf9fc 29615+ err = au_seq_path(seq, &path);
79b8bda9 29616+ if (!err) {
076b876e 29617+ au_optstr_br_perm(&perm, br->br_perm);
79b8bda9 29618+ seq_printf(seq, "=%s", perm.a);
5afbbe0d 29619+ if (bindex != bbot)
79b8bda9 29620+ seq_putc(seq, ':');
1e00d052 29621+ }
1facf9fc 29622+ }
79b8bda9
AM
29623+ if (unlikely(err || seq_has_overflowed(seq)))
29624+ err = -E2BIG;
1facf9fc 29625+
29626+ return err;
29627+}
29628+
f2c43d5f
AM
29629+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat,
29630+ const char *append)
29631+{
29632+ char *p;
29633+
29634+ p = fmt;
29635+ while (*pat != ':')
29636+ *p++ = *pat++;
29637+ *p++ = *pat++;
29638+ strcpy(p, append);
29639+ AuDebugOn(strlen(fmt) >= len);
29640+}
29641+
1facf9fc 29642+static void au_show_wbr_create(struct seq_file *m, int v,
29643+ struct au_sbinfo *sbinfo)
29644+{
29645+ const char *pat;
f2c43d5f
AM
29646+ char fmt[32];
29647+ struct au_wbr_mfs *mfs;
1facf9fc 29648+
dece6358
AM
29649+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29650+
c2b27bf2 29651+ seq_puts(m, ",create=");
1facf9fc 29652+ pat = au_optstr_wbr_create(v);
f2c43d5f 29653+ mfs = &sbinfo->si_wbr_mfs;
1facf9fc 29654+ switch (v) {
29655+ case AuWbrCreate_TDP:
29656+ case AuWbrCreate_RR:
29657+ case AuWbrCreate_MFS:
29658+ case AuWbrCreate_PMFS:
c2b27bf2 29659+ seq_puts(m, pat);
1facf9fc 29660+ break;
f2c43d5f
AM
29661+ case AuWbrCreate_MFSRR:
29662+ case AuWbrCreate_TDMFS:
29663+ case AuWbrCreate_PMFSRR:
29664+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu");
29665+ seq_printf(m, fmt, mfs->mfsrr_watermark);
1facf9fc 29666+ break;
f2c43d5f 29667+ case AuWbrCreate_MFSV:
1facf9fc 29668+ case AuWbrCreate_PMFSV:
f2c43d5f
AM
29669+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu");
29670+ seq_printf(m, fmt,
29671+ jiffies_to_msecs(mfs->mfs_expire)
e49829fe 29672+ / MSEC_PER_SEC);
1facf9fc 29673+ break;
1facf9fc 29674+ case AuWbrCreate_MFSRRV:
f2c43d5f 29675+ case AuWbrCreate_TDMFSV:
392086de 29676+ case AuWbrCreate_PMFSRRV:
f2c43d5f
AM
29677+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu");
29678+ seq_printf(m, fmt, mfs->mfsrr_watermark,
29679+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC);
392086de 29680+ break;
f2c43d5f
AM
29681+ default:
29682+ BUG();
1facf9fc 29683+ }
29684+}
29685+
7eafdf33 29686+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 29687+{
29688+#ifdef CONFIG_SYSFS
29689+ return 0;
29690+#else
29691+ int err;
29692+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
29693+ aufs_bindex_t bindex, brid;
1facf9fc 29694+ struct qstr *name;
29695+ struct file *f;
29696+ struct dentry *d, *h_root;
acd2b654 29697+ struct au_branch *br;
1facf9fc 29698+
dece6358
AM
29699+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29700+
1facf9fc 29701+ err = 0;
1facf9fc 29702+ f = au_sbi(sb)->si_xib;
29703+ if (!f)
29704+ goto out;
29705+
29706+ /* stop printing the default xino path on the first writable branch */
29707+ h_root = NULL;
acd2b654
AM
29708+ bindex = au_xi_root(sb, f->f_path.dentry);
29709+ if (bindex >= 0) {
29710+ br = au_sbr_sb(sb, bindex);
29711+ h_root = au_br_dentry(br);
1facf9fc 29712+ }
acd2b654 29713+
2000de60 29714+ d = f->f_path.dentry;
1facf9fc 29715+ name = &d->d_name;
29716+ /* safe ->d_parent because the file is unlinked */
29717+ if (d->d_parent == h_root
29718+ && name->len == len
29719+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
29720+ goto out;
29721+
29722+ seq_puts(seq, ",xino=");
29723+ err = au_xino_path(seq, f);
29724+
4f0767ce 29725+out:
1facf9fc 29726+ return err;
29727+#endif
29728+}
29729+
29730+/* seq_file will re-call me in case of too long string */
7eafdf33 29731+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 29732+{
027c5e7a 29733+ int err;
1facf9fc 29734+ unsigned int mnt_flags, v;
29735+ struct super_block *sb;
29736+ struct au_sbinfo *sbinfo;
29737+
29738+#define AuBool(name, str) do { \
29739+ v = au_opt_test(mnt_flags, name); \
29740+ if (v != au_opt_test(AuOpt_Def, name)) \
29741+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
29742+} while (0)
29743+
29744+#define AuStr(name, str) do { \
29745+ v = mnt_flags & AuOptMask_##name; \
29746+ if (v != (AuOpt_Def & AuOptMask_##name)) \
29747+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
29748+} while (0)
29749+
29750+#define AuUInt(name, str, val) do { \
29751+ if (val != AUFS_##name##_DEF) \
29752+ seq_printf(m, "," #str "=%u", val); \
29753+} while (0)
29754+
7eafdf33 29755+ sb = dentry->d_sb;
2121bcd9 29756+ if (sb->s_flags & SB_POSIXACL)
c1595e42 29757+ seq_puts(m, ",acl");
be118d29
JR
29758+#if 0
29759+ if (sb->s_flags & SB_I_VERSION)
29760+ seq_puts(m, ",i_version");
29761+#endif
c1595e42
JR
29762+
29763+ /* lock free root dinfo */
1facf9fc 29764+ si_noflush_read_lock(sb);
29765+ sbinfo = au_sbi(sb);
29766+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
29767+
29768+ mnt_flags = au_mntflags(sb);
29769+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 29770+ err = au_show_xino(m, sb);
1facf9fc 29771+ if (unlikely(err))
29772+ goto out;
29773+ } else
29774+ seq_puts(m, ",noxino");
29775+
29776+ AuBool(TRUNC_XINO, trunc_xino);
29777+ AuStr(UDBA, udba);
dece6358 29778+ AuBool(SHWH, shwh);
1facf9fc 29779+ AuBool(PLINK, plink);
4a4d8108 29780+ AuBool(DIO, dio);
076b876e 29781+ AuBool(DIRPERM1, dirperm1);
1facf9fc 29782+
29783+ v = sbinfo->si_wbr_create;
29784+ if (v != AuWbrCreate_Def)
29785+ au_show_wbr_create(m, v, sbinfo);
29786+
29787+ v = sbinfo->si_wbr_copyup;
29788+ if (v != AuWbrCopyup_Def)
29789+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
29790+
29791+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
29792+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
29793+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
29794+
29795+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
29796+
027c5e7a
AM
29797+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
29798+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 29799+
29800+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
29801+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
29802+
076b876e
AM
29803+ au_fhsm_show(m, sbinfo);
29804+
8b6a4947 29805+ AuBool(DIRREN, dirren);
1facf9fc 29806+ AuBool(SUM, sum);
29807+ /* AuBool(SUM_W, wsum); */
29808+ AuBool(WARN_PERM, warn_perm);
29809+ AuBool(VERBOSE, verbose);
29810+
4f0767ce 29811+out:
1facf9fc 29812+ /* be sure to print "br:" last */
29813+ if (!sysaufs_brs) {
29814+ seq_puts(m, ",br:");
29815+ au_show_brs(m, sb);
29816+ }
29817+ si_read_unlock(sb);
29818+ return 0;
29819+
1facf9fc 29820+#undef AuBool
29821+#undef AuStr
4a4d8108 29822+#undef AuUInt
1facf9fc 29823+}
29824+
29825+/* ---------------------------------------------------------------------- */
29826+
29827+/* sum mode which returns the summation for statfs(2) */
29828+
29829+static u64 au_add_till_max(u64 a, u64 b)
29830+{
29831+ u64 old;
29832+
29833+ old = a;
29834+ a += b;
92d182d2
AM
29835+ if (old <= a)
29836+ return a;
29837+ return ULLONG_MAX;
29838+}
29839+
29840+static u64 au_mul_till_max(u64 a, long mul)
29841+{
29842+ u64 old;
29843+
29844+ old = a;
29845+ a *= mul;
29846+ if (old <= a)
1facf9fc 29847+ return a;
29848+ return ULLONG_MAX;
29849+}
29850+
29851+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
29852+{
29853+ int err;
92d182d2 29854+ long bsize, factor;
1facf9fc 29855+ u64 blocks, bfree, bavail, files, ffree;
5afbbe0d 29856+ aufs_bindex_t bbot, bindex, i;
1facf9fc 29857+ unsigned char shared;
7f207e10 29858+ struct path h_path;
1facf9fc 29859+ struct super_block *h_sb;
29860+
92d182d2
AM
29861+ err = 0;
29862+ bsize = LONG_MAX;
29863+ files = 0;
29864+ ffree = 0;
1facf9fc 29865+ blocks = 0;
29866+ bfree = 0;
29867+ bavail = 0;
5afbbe0d
AM
29868+ bbot = au_sbbot(sb);
29869+ for (bindex = 0; bindex <= bbot; bindex++) {
7f207e10
AM
29870+ h_path.mnt = au_sbr_mnt(sb, bindex);
29871+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 29872+ shared = 0;
92d182d2 29873+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 29874+ shared = (au_sbr_sb(sb, i) == h_sb);
29875+ if (shared)
29876+ continue;
29877+
29878+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29879+ h_path.dentry = h_path.mnt->mnt_root;
29880+ err = vfs_statfs(&h_path, buf);
1facf9fc 29881+ if (unlikely(err))
29882+ goto out;
29883+
92d182d2
AM
29884+ if (bsize > buf->f_bsize) {
29885+ /*
29886+ * we will reduce bsize, so we have to expand blocks
29887+ * etc. to match them again
29888+ */
29889+ factor = (bsize / buf->f_bsize);
29890+ blocks = au_mul_till_max(blocks, factor);
29891+ bfree = au_mul_till_max(bfree, factor);
29892+ bavail = au_mul_till_max(bavail, factor);
29893+ bsize = buf->f_bsize;
29894+ }
29895+
29896+ factor = (buf->f_bsize / bsize);
29897+ blocks = au_add_till_max(blocks,
29898+ au_mul_till_max(buf->f_blocks, factor));
29899+ bfree = au_add_till_max(bfree,
29900+ au_mul_till_max(buf->f_bfree, factor));
29901+ bavail = au_add_till_max(bavail,
29902+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 29903+ files = au_add_till_max(files, buf->f_files);
29904+ ffree = au_add_till_max(ffree, buf->f_ffree);
29905+ }
29906+
92d182d2 29907+ buf->f_bsize = bsize;
1facf9fc 29908+ buf->f_blocks = blocks;
29909+ buf->f_bfree = bfree;
29910+ buf->f_bavail = bavail;
29911+ buf->f_files = files;
29912+ buf->f_ffree = ffree;
92d182d2 29913+ buf->f_frsize = 0;
1facf9fc 29914+
4f0767ce 29915+out:
1facf9fc 29916+ return err;
29917+}
29918+
29919+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
29920+{
29921+ int err;
7f207e10 29922+ struct path h_path;
1facf9fc 29923+ struct super_block *sb;
29924+
29925+ /* lock free root dinfo */
29926+ sb = dentry->d_sb;
29927+ si_noflush_read_lock(sb);
7f207e10 29928+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 29929+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29930+ h_path.mnt = au_sbr_mnt(sb, 0);
29931+ h_path.dentry = h_path.mnt->mnt_root;
29932+ err = vfs_statfs(&h_path, buf);
29933+ } else
1facf9fc 29934+ err = au_statfs_sum(sb, buf);
29935+ si_read_unlock(sb);
29936+
29937+ if (!err) {
29938+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 29939+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 29940+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
29941+ }
29942+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
29943+
29944+ return err;
29945+}
29946+
29947+/* ---------------------------------------------------------------------- */
29948+
537831f9
AM
29949+static int aufs_sync_fs(struct super_block *sb, int wait)
29950+{
29951+ int err, e;
5afbbe0d 29952+ aufs_bindex_t bbot, bindex;
537831f9
AM
29953+ struct au_branch *br;
29954+ struct super_block *h_sb;
29955+
29956+ err = 0;
29957+ si_noflush_read_lock(sb);
5afbbe0d
AM
29958+ bbot = au_sbbot(sb);
29959+ for (bindex = 0; bindex <= bbot; bindex++) {
537831f9
AM
29960+ br = au_sbr(sb, bindex);
29961+ if (!au_br_writable(br->br_perm))
29962+ continue;
29963+
29964+ h_sb = au_sbr_sb(sb, bindex);
a2654f78
AM
29965+ e = vfsub_sync_filesystem(h_sb, wait);
29966+ if (unlikely(e && !err))
29967+ err = e;
29968+ /* go on even if an error happens */
537831f9
AM
29969+ }
29970+ si_read_unlock(sb);
29971+
29972+ return err;
29973+}
29974+
29975+/* ---------------------------------------------------------------------- */
29976+
1facf9fc 29977+/* final actions when unmounting a file system */
29978+static void aufs_put_super(struct super_block *sb)
29979+{
29980+ struct au_sbinfo *sbinfo;
29981+
29982+ sbinfo = au_sbi(sb);
062440b3
AM
29983+ if (sbinfo)
29984+ kobject_put(&sbinfo->si_kobj);
1facf9fc 29985+}
29986+
29987+/* ---------------------------------------------------------------------- */
29988+
79b8bda9
AM
29989+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
29990+ struct super_block *sb, void *arg)
7f207e10
AM
29991+{
29992+ void *array;
076b876e 29993+ unsigned long long n, sz;
7f207e10
AM
29994+
29995+ array = NULL;
29996+ n = 0;
29997+ if (!*hint)
29998+ goto out;
29999+
30000+ if (*hint > ULLONG_MAX / sizeof(array)) {
30001+ array = ERR_PTR(-EMFILE);
30002+ pr_err("hint %llu\n", *hint);
30003+ goto out;
30004+ }
30005+
076b876e
AM
30006+ sz = sizeof(array) * *hint;
30007+ array = kzalloc(sz, GFP_NOFS);
7f207e10 30008+ if (unlikely(!array))
076b876e 30009+ array = vzalloc(sz);
7f207e10
AM
30010+ if (unlikely(!array)) {
30011+ array = ERR_PTR(-ENOMEM);
30012+ goto out;
30013+ }
30014+
79b8bda9 30015+ n = cb(sb, array, *hint, arg);
7f207e10
AM
30016+ AuDebugOn(n > *hint);
30017+
30018+out:
30019+ *hint = n;
30020+ return array;
30021+}
30022+
79b8bda9 30023+static unsigned long long au_iarray_cb(struct super_block *sb, void *a,
7f207e10
AM
30024+ unsigned long long max __maybe_unused,
30025+ void *arg)
30026+{
30027+ unsigned long long n;
30028+ struct inode **p, *inode;
30029+ struct list_head *head;
30030+
30031+ n = 0;
30032+ p = a;
30033+ head = arg;
79b8bda9 30034+ spin_lock(&sb->s_inode_list_lock);
7f207e10 30035+ list_for_each_entry(inode, head, i_sb_list) {
5afbbe0d
AM
30036+ if (!au_is_bad_inode(inode)
30037+ && au_ii(inode)->ii_btop >= 0) {
2cbb1c4b
JR
30038+ spin_lock(&inode->i_lock);
30039+ if (atomic_read(&inode->i_count)) {
30040+ au_igrab(inode);
30041+ *p++ = inode;
30042+ n++;
30043+ AuDebugOn(n > max);
30044+ }
30045+ spin_unlock(&inode->i_lock);
7f207e10
AM
30046+ }
30047+ }
79b8bda9 30048+ spin_unlock(&sb->s_inode_list_lock);
7f207e10
AM
30049+
30050+ return n;
30051+}
30052+
30053+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
30054+{
acd2b654
AM
30055+ struct au_sbinfo *sbi;
30056+
30057+ sbi = au_sbi(sb);
30058+ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1);
79b8bda9 30059+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes);
7f207e10
AM
30060+}
30061+
30062+void au_iarray_free(struct inode **a, unsigned long long max)
30063+{
30064+ unsigned long long ull;
30065+
30066+ for (ull = 0; ull < max; ull++)
30067+ iput(a[ull]);
be52b249 30068+ kvfree(a);
7f207e10
AM
30069+}
30070+
30071+/* ---------------------------------------------------------------------- */
30072+
1facf9fc 30073+/*
30074+ * refresh dentry and inode at remount time.
30075+ */
027c5e7a
AM
30076+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
30077+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
30078+ struct dentry *parent)
1facf9fc 30079+{
30080+ int err;
1facf9fc 30081+
30082+ di_write_lock_child(dentry);
1facf9fc 30083+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
30084+ err = au_refresh_dentry(dentry, parent);
30085+ if (!err && dir_flags)
5527c038 30086+ au_hn_reset(d_inode(dentry), dir_flags);
1facf9fc 30087+ di_read_unlock(parent, AuLock_IR);
1facf9fc 30088+ di_write_unlock(dentry);
30089+
30090+ return err;
30091+}
30092+
027c5e7a
AM
30093+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
30094+ struct au_sbinfo *sbinfo,
b95c5147 30095+ const unsigned int dir_flags, unsigned int do_idop)
1facf9fc 30096+{
027c5e7a
AM
30097+ int err;
30098+ struct dentry *parent;
027c5e7a
AM
30099+
30100+ err = 0;
30101+ parent = dget_parent(dentry);
30102+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
5527c038
JR
30103+ if (d_really_is_positive(dentry)) {
30104+ if (!d_is_dir(dentry))
027c5e7a
AM
30105+ err = au_do_refresh(dentry, /*dir_flags*/0,
30106+ parent);
30107+ else {
30108+ err = au_do_refresh(dentry, dir_flags, parent);
30109+ if (unlikely(err))
30110+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
30111+ }
30112+ } else
30113+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
30114+ AuDbgDentry(dentry);
30115+ }
30116+ dput(parent);
30117+
79b8bda9 30118+ if (!err) {
b95c5147 30119+ if (do_idop)
79b8bda9
AM
30120+ au_refresh_dop(dentry, /*force_reval*/0);
30121+ } else
30122+ au_refresh_dop(dentry, /*force_reval*/1);
30123+
027c5e7a
AM
30124+ AuTraceErr(err);
30125+ return err;
1facf9fc 30126+}
30127+
b95c5147 30128+static int au_refresh_d(struct super_block *sb, unsigned int do_idop)
1facf9fc 30129+{
30130+ int err, i, j, ndentry, e;
027c5e7a 30131+ unsigned int sigen;
1facf9fc 30132+ struct au_dcsub_pages dpages;
30133+ struct au_dpage *dpage;
027c5e7a
AM
30134+ struct dentry **dentries, *d;
30135+ struct au_sbinfo *sbinfo;
30136+ struct dentry *root = sb->s_root;
5527c038 30137+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1);
1facf9fc 30138+
b95c5147 30139+ if (do_idop)
79b8bda9
AM
30140+ au_refresh_dop(root, /*force_reval*/0);
30141+
027c5e7a
AM
30142+ err = au_dpages_init(&dpages, GFP_NOFS);
30143+ if (unlikely(err))
1facf9fc 30144+ goto out;
027c5e7a
AM
30145+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
30146+ if (unlikely(err))
1facf9fc 30147+ goto out_dpages;
1facf9fc 30148+
027c5e7a
AM
30149+ sigen = au_sigen(sb);
30150+ sbinfo = au_sbi(sb);
30151+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 30152+ dpage = dpages.dpages + i;
30153+ dentries = dpage->dentries;
30154+ ndentry = dpage->ndentry;
027c5e7a 30155+ for (j = 0; j < ndentry; j++) {
1facf9fc 30156+ d = dentries[j];
79b8bda9 30157+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags,
b95c5147 30158+ do_idop);
027c5e7a
AM
30159+ if (unlikely(e && !err))
30160+ err = e;
30161+ /* go on even err */
1facf9fc 30162+ }
30163+ }
30164+
4f0767ce 30165+out_dpages:
1facf9fc 30166+ au_dpages_free(&dpages);
4f0767ce 30167+out:
1facf9fc 30168+ return err;
30169+}
30170+
b95c5147 30171+static int au_refresh_i(struct super_block *sb, unsigned int do_idop)
1facf9fc 30172+{
027c5e7a
AM
30173+ int err, e;
30174+ unsigned int sigen;
30175+ unsigned long long max, ull;
30176+ struct inode *inode, **array;
1facf9fc 30177+
027c5e7a
AM
30178+ array = au_iarray_alloc(sb, &max);
30179+ err = PTR_ERR(array);
30180+ if (IS_ERR(array))
30181+ goto out;
1facf9fc 30182+
30183+ err = 0;
027c5e7a
AM
30184+ sigen = au_sigen(sb);
30185+ for (ull = 0; ull < max; ull++) {
30186+ inode = array[ull];
076b876e
AM
30187+ if (unlikely(!inode))
30188+ break;
b95c5147
AM
30189+
30190+ e = 0;
30191+ ii_write_lock_child(inode);
537831f9 30192+ if (au_iigen(inode, NULL) != sigen) {
027c5e7a 30193+ e = au_refresh_hinode_self(inode);
1facf9fc 30194+ if (unlikely(e)) {
b95c5147 30195+ au_refresh_iop(inode, /*force_getattr*/1);
027c5e7a 30196+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 30197+ if (!err)
30198+ err = e;
30199+ /* go on even if err */
30200+ }
30201+ }
b95c5147
AM
30202+ if (!e && do_idop)
30203+ au_refresh_iop(inode, /*force_getattr*/0);
30204+ ii_write_unlock(inode);
1facf9fc 30205+ }
30206+
027c5e7a 30207+ au_iarray_free(array, max);
1facf9fc 30208+
4f0767ce 30209+out:
1facf9fc 30210+ return err;
30211+}
30212+
b95c5147 30213+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
1facf9fc 30214+{
027c5e7a
AM
30215+ int err, e;
30216+ unsigned int udba;
5afbbe0d 30217+ aufs_bindex_t bindex, bbot;
1facf9fc 30218+ struct dentry *root;
30219+ struct inode *inode;
027c5e7a 30220+ struct au_branch *br;
79b8bda9 30221+ struct au_sbinfo *sbi;
1facf9fc 30222+
30223+ au_sigen_inc(sb);
79b8bda9
AM
30224+ sbi = au_sbi(sb);
30225+ au_fclr_si(sbi, FAILED_REFRESH_DIR);
1facf9fc 30226+
30227+ root = sb->s_root;
30228+ DiMustNoWaiters(root);
5527c038 30229+ inode = d_inode(root);
1facf9fc 30230+ IiMustNoWaiters(inode);
1facf9fc 30231+
027c5e7a 30232+ udba = au_opt_udba(sb);
5afbbe0d
AM
30233+ bbot = au_sbbot(sb);
30234+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
30235+ br = au_sbr(sb, bindex);
30236+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 30237+ if (unlikely(err))
027c5e7a
AM
30238+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
30239+ bindex, err);
30240+ /* go on even if err */
1facf9fc 30241+ }
027c5e7a 30242+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 30243+
b95c5147 30244+ if (do_idop) {
79b8bda9
AM
30245+ if (au_ftest_si(sbi, NO_DREVAL)) {
30246+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval);
30247+ sb->s_d_op = &aufs_dop_noreval;
b95c5147
AM
30248+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr);
30249+ sbi->si_iop_array = aufs_iop_nogetattr;
79b8bda9
AM
30250+ } else {
30251+ AuDebugOn(sb->s_d_op == &aufs_dop);
30252+ sb->s_d_op = &aufs_dop;
b95c5147
AM
30253+ AuDebugOn(sbi->si_iop_array == aufs_iop);
30254+ sbi->si_iop_array = aufs_iop;
79b8bda9 30255+ }
062440b3 30256+ pr_info("reset to %ps and %ps\n",
b95c5147 30257+ sb->s_d_op, sbi->si_iop_array);
79b8bda9
AM
30258+ }
30259+
027c5e7a 30260+ di_write_unlock(root);
b95c5147
AM
30261+ err = au_refresh_d(sb, do_idop);
30262+ e = au_refresh_i(sb, do_idop);
027c5e7a
AM
30263+ if (unlikely(e && !err))
30264+ err = e;
1facf9fc 30265+ /* aufs_write_lock() calls ..._child() */
30266+ di_write_lock_child(root);
027c5e7a
AM
30267+
30268+ au_cpup_attr_all(inode, /*force*/1);
30269+
30270+ if (unlikely(err))
30271+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 30272+}
30273+
30274+/* stop extra interpretation of errno in mount(8), and strange error messages */
30275+static int cvt_err(int err)
30276+{
30277+ AuTraceErr(err);
30278+
30279+ switch (err) {
30280+ case -ENOENT:
30281+ case -ENOTDIR:
30282+ case -EEXIST:
30283+ case -EIO:
30284+ err = -EINVAL;
30285+ }
30286+ return err;
30287+}
30288+
30289+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
30290+{
4a4d8108
AM
30291+ int err, do_dx;
30292+ unsigned int mntflags;
be52b249
AM
30293+ struct au_opts opts = {
30294+ .opt = NULL
30295+ };
1facf9fc 30296+ struct dentry *root;
30297+ struct inode *inode;
30298+ struct au_sbinfo *sbinfo;
30299+
30300+ err = 0;
30301+ root = sb->s_root;
30302+ if (!data || !*data) {
e49829fe
JR
30303+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30304+ if (!err) {
30305+ di_write_lock_child(root);
30306+ err = au_opts_verify(sb, *flags, /*pending*/0);
30307+ aufs_write_unlock(root);
30308+ }
1facf9fc 30309+ goto out;
30310+ }
30311+
30312+ err = -ENOMEM;
1facf9fc 30313+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30314+ if (unlikely(!opts.opt))
30315+ goto out;
30316+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30317+ opts.flags = AuOpts_REMOUNT;
30318+ opts.sb_flags = *flags;
30319+
30320+ /* parse it before aufs lock */
30321+ err = au_opts_parse(sb, data, &opts);
30322+ if (unlikely(err))
30323+ goto out_opts;
30324+
30325+ sbinfo = au_sbi(sb);
5527c038 30326+ inode = d_inode(root);
febd17d6 30327+ inode_lock(inode);
e49829fe
JR
30328+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30329+ if (unlikely(err))
30330+ goto out_mtx;
30331+ di_write_lock_child(root);
1facf9fc 30332+
30333+ /* au_opts_remount() may return an error */
30334+ err = au_opts_remount(sb, &opts);
30335+ au_opts_free(&opts);
30336+
027c5e7a 30337+ if (au_ftest_opts(opts.flags, REFRESH))
b95c5147 30338+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP));
1facf9fc 30339+
4a4d8108
AM
30340+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
30341+ mntflags = au_mntflags(sb);
30342+ do_dx = !!au_opt_test(mntflags, DIO);
30343+ au_dy_arefresh(do_dx);
30344+ }
30345+
076b876e 30346+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */
1facf9fc 30347+ aufs_write_unlock(root);
953406b4 30348+
e49829fe 30349+out_mtx:
febd17d6 30350+ inode_unlock(inode);
4f0767ce 30351+out_opts:
1c60b727 30352+ free_page((unsigned long)opts.opt);
4f0767ce 30353+out:
1facf9fc 30354+ err = cvt_err(err);
30355+ AuTraceErr(err);
30356+ return err;
30357+}
30358+
4a4d8108 30359+static const struct super_operations aufs_sop = {
1facf9fc 30360+ .alloc_inode = aufs_alloc_inode,
30361+ .destroy_inode = aufs_destroy_inode,
fbc438ed 30362+ .free_inode = aufs_free_inode,
b752ccd1 30363+ /* always deleting, no clearing */
1facf9fc 30364+ .drop_inode = generic_delete_inode,
30365+ .show_options = aufs_show_options,
30366+ .statfs = aufs_statfs,
30367+ .put_super = aufs_put_super,
537831f9 30368+ .sync_fs = aufs_sync_fs,
1facf9fc 30369+ .remount_fs = aufs_remount_fs
30370+};
30371+
30372+/* ---------------------------------------------------------------------- */
30373+
30374+static int alloc_root(struct super_block *sb)
30375+{
30376+ int err;
30377+ struct inode *inode;
30378+ struct dentry *root;
30379+
30380+ err = -ENOMEM;
30381+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
30382+ err = PTR_ERR(inode);
30383+ if (IS_ERR(inode))
30384+ goto out;
30385+
b95c5147 30386+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */
1facf9fc 30387+ inode->i_fop = &aufs_dir_fop;
30388+ inode->i_mode = S_IFDIR;
9dbd164d 30389+ set_nlink(inode, 2);
1facf9fc 30390+ unlock_new_inode(inode);
30391+
92d182d2 30392+ root = d_make_root(inode);
1facf9fc 30393+ if (unlikely(!root))
92d182d2 30394+ goto out;
1facf9fc 30395+ err = PTR_ERR(root);
30396+ if (IS_ERR(root))
92d182d2 30397+ goto out;
1facf9fc 30398+
4a4d8108 30399+ err = au_di_init(root);
1facf9fc 30400+ if (!err) {
30401+ sb->s_root = root;
30402+ return 0; /* success */
30403+ }
30404+ dput(root);
1facf9fc 30405+
4f0767ce 30406+out:
1facf9fc 30407+ return err;
1facf9fc 30408+}
30409+
30410+static int aufs_fill_super(struct super_block *sb, void *raw_data,
30411+ int silent __maybe_unused)
30412+{
30413+ int err;
be52b249
AM
30414+ struct au_opts opts = {
30415+ .opt = NULL
30416+ };
79b8bda9 30417+ struct au_sbinfo *sbinfo;
1facf9fc 30418+ struct dentry *root;
30419+ struct inode *inode;
30420+ char *arg = raw_data;
30421+
30422+ if (unlikely(!arg || !*arg)) {
30423+ err = -EINVAL;
4a4d8108 30424+ pr_err("no arg\n");
1facf9fc 30425+ goto out;
30426+ }
30427+
30428+ err = -ENOMEM;
1facf9fc 30429+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30430+ if (unlikely(!opts.opt))
30431+ goto out;
30432+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30433+ opts.sb_flags = sb->s_flags;
30434+
30435+ err = au_si_alloc(sb);
30436+ if (unlikely(err))
30437+ goto out_opts;
79b8bda9 30438+ sbinfo = au_sbi(sb);
1facf9fc 30439+
30440+ /* all timestamps always follow the ones on the branch */
2121bcd9 30441+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
be118d29 30442+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */
1facf9fc 30443+ sb->s_op = &aufs_sop;
027c5e7a 30444+ sb->s_d_op = &aufs_dop;
1facf9fc 30445+ sb->s_magic = AUFS_SUPER_MAGIC;
30446+ sb->s_maxbytes = 0;
c1595e42 30447+ sb->s_stack_depth = 1;
1facf9fc 30448+ au_export_init(sb);
f2c43d5f 30449+ au_xattr_init(sb);
1facf9fc 30450+
30451+ err = alloc_root(sb);
30452+ if (unlikely(err)) {
30453+ si_write_unlock(sb);
30454+ goto out_info;
30455+ }
30456+ root = sb->s_root;
5527c038 30457+ inode = d_inode(root);
1facf9fc 30458+
30459+ /*
30460+ * actually we can parse options regardless aufs lock here.
30461+ * but at remount time, parsing must be done before aufs lock.
30462+ * so we follow the same rule.
30463+ */
30464+ ii_write_lock_parent(inode);
30465+ aufs_write_unlock(root);
30466+ err = au_opts_parse(sb, arg, &opts);
30467+ if (unlikely(err))
30468+ goto out_root;
30469+
30470+ /* lock vfs_inode first, then aufs. */
febd17d6 30471+ inode_lock(inode);
1facf9fc 30472+ aufs_write_lock(root);
30473+ err = au_opts_mount(sb, &opts);
30474+ au_opts_free(&opts);
79b8bda9
AM
30475+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
30476+ sb->s_d_op = &aufs_dop_noreval;
062440b3 30477+ pr_info("%ps\n", sb->s_d_op);
79b8bda9 30478+ au_refresh_dop(root, /*force_reval*/0);
b95c5147
AM
30479+ sbinfo->si_iop_array = aufs_iop_nogetattr;
30480+ au_refresh_iop(inode, /*force_getattr*/0);
79b8bda9 30481+ }
1facf9fc 30482+ aufs_write_unlock(root);
febd17d6 30483+ inode_unlock(inode);
4a4d8108
AM
30484+ if (!err)
30485+ goto out_opts; /* success */
1facf9fc 30486+
4f0767ce 30487+out_root:
1facf9fc 30488+ dput(root);
30489+ sb->s_root = NULL;
4f0767ce 30490+out_info:
79b8bda9 30491+ kobject_put(&sbinfo->si_kobj);
1facf9fc 30492+ sb->s_fs_info = NULL;
4f0767ce 30493+out_opts:
1c60b727 30494+ free_page((unsigned long)opts.opt);
4f0767ce 30495+out:
1facf9fc 30496+ AuTraceErr(err);
30497+ err = cvt_err(err);
30498+ AuTraceErr(err);
30499+ return err;
30500+}
30501+
30502+/* ---------------------------------------------------------------------- */
30503+
027c5e7a
AM
30504+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
30505+ const char *dev_name __maybe_unused,
30506+ void *raw_data)
1facf9fc 30507+{
027c5e7a 30508+ struct dentry *root;
1facf9fc 30509+
30510+ /* all timestamps always follow the ones on the branch */
30511+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
30512+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
30513+ if (IS_ERR(root))
30514+ goto out;
30515+
062440b3 30516+ au_sbilist_add(root->d_sb);
027c5e7a
AM
30517+
30518+out:
30519+ return root;
1facf9fc 30520+}
30521+
e49829fe
JR
30522+static void aufs_kill_sb(struct super_block *sb)
30523+{
30524+ struct au_sbinfo *sbinfo;
30525+
30526+ sbinfo = au_sbi(sb);
30527+ if (sbinfo) {
30528+ au_sbilist_del(sb);
30529+ aufs_write_lock(sb->s_root);
076b876e 30530+ au_fhsm_fin(sb);
e49829fe
JR
30531+ if (sbinfo->si_wbr_create_ops->fin)
30532+ sbinfo->si_wbr_create_ops->fin(sb);
30533+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
30534+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
b95c5147 30535+ au_remount_refresh(sb, /*do_idop*/0);
e49829fe
JR
30536+ }
30537+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
30538+ au_plink_put(sb, /*verbose*/1);
30539+ au_xino_clr(sb);
8b6a4947 30540+ au_dr_opt_flush(sb);
1e00d052 30541+ sbinfo->si_sb = NULL;
e49829fe 30542+ aufs_write_unlock(sb->s_root);
e49829fe
JR
30543+ au_nwt_flush(&sbinfo->si_nowait);
30544+ }
98d9a5b1 30545+ kill_anon_super(sb);
e49829fe
JR
30546+}
30547+
1facf9fc 30548+struct file_system_type aufs_fs_type = {
30549+ .name = AUFS_FSTYPE,
c06a8ce3
AM
30550+ /* a race between rename and others */
30551+ .fs_flags = FS_RENAME_DOES_D_MOVE,
027c5e7a 30552+ .mount = aufs_mount,
e49829fe 30553+ .kill_sb = aufs_kill_sb,
1facf9fc 30554+ /* no need to __module_get() and module_put(). */
30555+ .owner = THIS_MODULE,
30556+};
7f207e10 30557diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
fbc438ed
JR
30558--- /usr/share/empty/fs/aufs/super.h 1970-01-01 08:00:00.000000000 +0800
30559+++ linux/fs/aufs/super.h 2019-07-11 21:21:54.382384486 +0800
acd2b654 30560@@ -0,0 +1,589 @@
062440b3 30561+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 30562+/*
ba1aed25 30563+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 30564+ *
30565+ * This program, aufs is free software; you can redistribute it and/or modify
30566+ * it under the terms of the GNU General Public License as published by
30567+ * the Free Software Foundation; either version 2 of the License, or
30568+ * (at your option) any later version.
dece6358
AM
30569+ *
30570+ * This program is distributed in the hope that it will be useful,
30571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30573+ * GNU General Public License for more details.
30574+ *
30575+ * You should have received a copy of the GNU General Public License
523b37e3 30576+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30577+ */
30578+
30579+/*
30580+ * super_block operations
30581+ */
30582+
30583+#ifndef __AUFS_SUPER_H__
30584+#define __AUFS_SUPER_H__
30585+
30586+#ifdef __KERNEL__
30587+
30588+#include <linux/fs.h>
5527c038 30589+#include <linux/kobject.h>
8b6a4947 30590+#include "hbl.h"
acd2b654 30591+#include "lcnt.h"
1facf9fc 30592+#include "rwsem.h"
1facf9fc 30593+#include "wkq.h"
30594+
1facf9fc 30595+/* policies to select one among multiple writable branches */
30596+struct au_wbr_copyup_operations {
30597+ int (*copyup)(struct dentry *dentry);
30598+};
30599+
392086de
AM
30600+#define AuWbr_DIR 1 /* target is a dir */
30601+#define AuWbr_PARENT (1 << 1) /* always require a parent */
30602+
30603+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name)
30604+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; }
30605+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; }
30606+
1facf9fc 30607+struct au_wbr_create_operations {
392086de 30608+ int (*create)(struct dentry *dentry, unsigned int flags);
1facf9fc 30609+ int (*init)(struct super_block *sb);
30610+ int (*fin)(struct super_block *sb);
30611+};
30612+
30613+struct au_wbr_mfs {
30614+ struct mutex mfs_lock; /* protect this structure */
30615+ unsigned long mfs_jiffy;
30616+ unsigned long mfs_expire;
30617+ aufs_bindex_t mfs_bindex;
30618+
30619+ unsigned long long mfsrr_bytes;
30620+ unsigned long long mfsrr_watermark;
30621+};
30622+
86dc4139
AM
30623+#define AuPlink_NHASH 100
30624+static inline int au_plink_hash(ino_t ino)
30625+{
30626+ return ino % AuPlink_NHASH;
30627+}
30628+
076b876e
AM
30629+/* File-based Hierarchical Storage Management */
30630+struct au_fhsm {
30631+#ifdef CONFIG_AUFS_FHSM
30632+ /* allow only one process who can receive the notification */
30633+ spinlock_t fhsm_spin;
30634+ pid_t fhsm_pid;
30635+ wait_queue_head_t fhsm_wqh;
30636+ atomic_t fhsm_readable;
30637+
c1595e42 30638+ /* these are protected by si_rwsem */
076b876e 30639+ unsigned long fhsm_expire;
c1595e42 30640+ aufs_bindex_t fhsm_bottom;
076b876e
AM
30641+#endif
30642+};
30643+
1facf9fc 30644+struct au_branch;
30645+struct au_sbinfo {
30646+ /* nowait tasks in the system-wide workqueue */
30647+ struct au_nowait_tasks si_nowait;
30648+
b752ccd1 30649+ /*
acd2b654 30650+ * tried sb->s_umount, but failed due to the dependency between i_mutex.
b752ccd1
AM
30651+ * rwsem for au_sbinfo is necessary.
30652+ */
dece6358 30653+ struct au_rwsem si_rwsem;
1facf9fc 30654+
7f207e10 30655+ /*
523b37e3
AM
30656+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from
30657+ * remount.
7f207e10 30658+ */
acd2b654 30659+ au_lcnt_t si_ninodes, si_nfiles;
7f207e10 30660+
1facf9fc 30661+ /* branch management */
30662+ unsigned int si_generation;
30663+
2000de60 30664+ /* see AuSi_ flags */
1facf9fc 30665+ unsigned char au_si_status;
30666+
5afbbe0d 30667+ aufs_bindex_t si_bbot;
7f207e10
AM
30668+
30669+ /* dirty trick to keep br_id plus */
30670+ unsigned int si_last_br_id :
30671+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 30672+ struct au_branch **si_branch;
30673+
30674+ /* policy to select a writable branch */
30675+ unsigned char si_wbr_copyup;
30676+ unsigned char si_wbr_create;
30677+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
30678+ struct au_wbr_create_operations *si_wbr_create_ops;
30679+
30680+ /* round robin */
30681+ atomic_t si_wbr_rr_next;
30682+
30683+ /* most free space */
30684+ struct au_wbr_mfs si_wbr_mfs;
30685+
076b876e
AM
30686+ /* File-based Hierarchical Storage Management */
30687+ struct au_fhsm si_fhsm;
30688+
1facf9fc 30689+ /* mount flags */
30690+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
30691+ unsigned int si_mntflags;
30692+
30693+ /* external inode number (bitmap and translation table) */
5527c038
JR
30694+ vfs_readf_t si_xread;
30695+ vfs_writef_t si_xwrite;
acd2b654
AM
30696+ loff_t si_ximaxent; /* max entries in a xino */
30697+
1facf9fc 30698+ struct file *si_xib;
30699+ struct mutex si_xib_mtx; /* protect xib members */
30700+ unsigned long *si_xib_buf;
30701+ unsigned long si_xib_last_pindex;
30702+ int si_xib_next_bit;
acd2b654 30703+
392086de
AM
30704+ unsigned long si_xino_jiffy;
30705+ unsigned long si_xino_expire;
1facf9fc 30706+ /* reserved for future use */
30707+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
30708+
30709+#ifdef CONFIG_AUFS_EXPORT
30710+ /* i_generation */
acd2b654 30711+ /* todo: make xigen file an array to support many inode numbers */
1facf9fc 30712+ struct file *si_xigen;
30713+ atomic_t si_xigen_next;
30714+#endif
30715+
acd2b654 30716+ /* dirty trick to support atomic_open */
8b6a4947 30717+ struct hlist_bl_head si_aopen;
b912730e 30718+
1facf9fc 30719+ /* vdir parameters */
e49829fe 30720+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 30721+ unsigned int si_rdblk; /* deblk size */
30722+ unsigned int si_rdhash; /* hash size */
30723+
30724+ /*
30725+ * If the number of whiteouts are larger than si_dirwh, leave all of
30726+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
30727+ * future fsck.aufs or kernel thread will remove them later.
30728+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
30729+ */
30730+ unsigned int si_dirwh;
30731+
1facf9fc 30732+ /* pseudo_link list */
8b6a4947 30733+ struct hlist_bl_head si_plink[AuPlink_NHASH];
1facf9fc 30734+ wait_queue_head_t si_plink_wq;
4a4d8108 30735+ spinlock_t si_plink_maint_lock;
e49829fe 30736+ pid_t si_plink_maint_pid;
1facf9fc 30737+
523b37e3 30738+ /* file list */
8b6a4947 30739+ struct hlist_bl_head si_files;
523b37e3 30740+
b95c5147
AM
30741+ /* with/without getattr, brother of sb->s_d_op */
30742+ struct inode_operations *si_iop_array;
30743+
1facf9fc 30744+ /*
30745+ * sysfs and lifetime management.
30746+ * this is not a small structure and it may be a waste of memory in case
acd2b654 30747+ * of sysfs is disabled, particularly when many aufs-es are mounted.
1facf9fc 30748+ * but using sysfs is majority.
30749+ */
30750+ struct kobject si_kobj;
30751+#ifdef CONFIG_DEBUG_FS
86dc4139
AM
30752+ struct dentry *si_dbgaufs;
30753+ struct dentry *si_dbgaufs_plink;
30754+ struct dentry *si_dbgaufs_xib;
1facf9fc 30755+#ifdef CONFIG_AUFS_EXPORT
30756+ struct dentry *si_dbgaufs_xigen;
30757+#endif
30758+#endif
30759+
e49829fe 30760+#ifdef CONFIG_AUFS_SBILIST
8b6a4947 30761+ struct hlist_bl_node si_list;
e49829fe
JR
30762+#endif
30763+
1facf9fc 30764+ /* dirty, necessary for unmounting, sysfs and sysrq */
30765+ struct super_block *si_sb;
30766+};
30767+
dece6358
AM
30768+/* sbinfo status flags */
30769+/*
30770+ * set true when refresh_dirs() failed at remount time.
30771+ * then try refreshing dirs at access time again.
062440b3 30772+ * if it is false, refreshing dirs at access time is unnecessary
dece6358 30773+ */
027c5e7a 30774+#define AuSi_FAILED_REFRESH_DIR 1
076b876e 30775+#define AuSi_FHSM (1 << 1) /* fhsm is active now */
79b8bda9 30776+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */
076b876e
AM
30777+
30778+#ifndef CONFIG_AUFS_FHSM
30779+#undef AuSi_FHSM
30780+#define AuSi_FHSM 0
30781+#endif
30782+
dece6358
AM
30783+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
30784+ unsigned int flag)
30785+{
30786+ AuRwMustAnyLock(&sbi->si_rwsem);
30787+ return sbi->au_si_status & flag;
30788+}
30789+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
30790+#define au_fset_si(sbinfo, name) do { \
30791+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30792+ (sbinfo)->au_si_status |= AuSi_##name; \
30793+} while (0)
30794+#define au_fclr_si(sbinfo, name) do { \
30795+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30796+ (sbinfo)->au_si_status &= ~AuSi_##name; \
30797+} while (0)
30798+
1facf9fc 30799+/* ---------------------------------------------------------------------- */
30800+
30801+/* policy to select one among writable branches */
4a4d8108
AM
30802+#define AuWbrCopyup(sbinfo, ...) \
30803+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
30804+#define AuWbrCreate(sbinfo, ...) \
30805+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 30806+
30807+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
30808+#define AuLock_DW 1 /* write-lock dentry */
30809+#define AuLock_IR (1 << 1) /* read-lock inode */
30810+#define AuLock_IW (1 << 2) /* write-lock inode */
30811+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
b95c5147 30812+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */
f2c43d5f 30813+ /* except RENAME_EXCHANGE */
e49829fe
JR
30814+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
30815+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 30816+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 30817+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
30818+#define au_fset_lock(flags, name) \
30819+ do { (flags) |= AuLock_##name; } while (0)
30820+#define au_fclr_lock(flags, name) \
30821+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 30822+
30823+/* ---------------------------------------------------------------------- */
30824+
30825+/* super.c */
30826+extern struct file_system_type aufs_fs_type;
30827+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
79b8bda9
AM
30828+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array,
30829+ unsigned long long max, void *arg);
79b8bda9
AM
30830+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
30831+ struct super_block *sb, void *arg);
7f207e10
AM
30832+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
30833+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 30834+
30835+/* sbinfo.c */
30836+void au_si_free(struct kobject *kobj);
30837+int au_si_alloc(struct super_block *sb);
e2f27e51 30838+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink);
1facf9fc 30839+
30840+unsigned int au_sigen_inc(struct super_block *sb);
30841+aufs_bindex_t au_new_br_id(struct super_block *sb);
30842+
e49829fe
JR
30843+int si_read_lock(struct super_block *sb, int flags);
30844+int si_write_lock(struct super_block *sb, int flags);
30845+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 30846+void aufs_read_unlock(struct dentry *dentry, int flags);
30847+void aufs_write_lock(struct dentry *dentry);
30848+void aufs_write_unlock(struct dentry *dentry);
e49829fe 30849+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 30850+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
30851+
30852+/* wbr_policy.c */
30853+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
30854+extern struct au_wbr_create_operations au_wbr_create_ops[];
30855+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
c2b27bf2 30856+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex);
5afbbe0d 30857+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop);
c2b27bf2
AM
30858+
30859+/* mvdown.c */
30860+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg);
1facf9fc 30861+
076b876e
AM
30862+#ifdef CONFIG_AUFS_FHSM
30863+/* fhsm.c */
30864+
30865+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm)
30866+{
30867+ pid_t pid;
30868+
30869+ spin_lock(&fhsm->fhsm_spin);
30870+ pid = fhsm->fhsm_pid;
30871+ spin_unlock(&fhsm->fhsm_spin);
30872+
30873+ return pid;
30874+}
30875+
30876+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force);
30877+void au_fhsm_wrote_all(struct super_block *sb, int force);
30878+int au_fhsm_fd(struct super_block *sb, int oflags);
30879+int au_fhsm_br_alloc(struct au_branch *br);
c1595e42 30880+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex);
076b876e
AM
30881+void au_fhsm_fin(struct super_block *sb);
30882+void au_fhsm_init(struct au_sbinfo *sbinfo);
30883+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec);
30884+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo);
30885+#else
30886+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex,
30887+ int force)
30888+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force)
30889+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags)
c1595e42
JR
30890+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm)
30891+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br)
30892+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex)
076b876e
AM
30893+AuStubVoid(au_fhsm_fin, struct super_block *sb)
30894+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo)
30895+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec)
30896+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo)
30897+#endif
30898+
1facf9fc 30899+/* ---------------------------------------------------------------------- */
30900+
30901+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
30902+{
30903+ return sb->s_fs_info;
30904+}
30905+
30906+/* ---------------------------------------------------------------------- */
30907+
30908+#ifdef CONFIG_AUFS_EXPORT
a2a7ad62 30909+int au_test_nfsd(void);
1facf9fc 30910+void au_export_init(struct super_block *sb);
b752ccd1 30911+void au_xigen_inc(struct inode *inode);
1facf9fc 30912+int au_xigen_new(struct inode *inode);
062440b3 30913+int au_xigen_set(struct super_block *sb, struct path *path);
1facf9fc 30914+void au_xigen_clr(struct super_block *sb);
30915+
30916+static inline int au_busy_or_stale(void)
30917+{
b752ccd1 30918+ if (!au_test_nfsd())
1facf9fc 30919+ return -EBUSY;
30920+ return -ESTALE;
30921+}
30922+#else
b752ccd1 30923+AuStubInt0(au_test_nfsd, void)
a2a7ad62 30924+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1 30925+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108 30926+AuStubInt0(au_xigen_new, struct inode *inode)
062440b3 30927+AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path)
4a4d8108 30928+AuStubVoid(au_xigen_clr, struct super_block *sb)
c1595e42 30929+AuStub(int, au_busy_or_stale, return -EBUSY, void)
1facf9fc 30930+#endif /* CONFIG_AUFS_EXPORT */
30931+
30932+/* ---------------------------------------------------------------------- */
30933+
e49829fe
JR
30934+#ifdef CONFIG_AUFS_SBILIST
30935+/* module.c */
8b6a4947 30936+extern struct hlist_bl_head au_sbilist;
e49829fe
JR
30937+
30938+static inline void au_sbilist_init(void)
30939+{
8b6a4947 30940+ INIT_HLIST_BL_HEAD(&au_sbilist);
e49829fe
JR
30941+}
30942+
30943+static inline void au_sbilist_add(struct super_block *sb)
30944+{
8b6a4947 30945+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe
JR
30946+}
30947+
30948+static inline void au_sbilist_del(struct super_block *sb)
30949+{
8b6a4947 30950+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe 30951+}
53392da6
AM
30952+
30953+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
30954+static inline void au_sbilist_lock(void)
30955+{
8b6a4947 30956+ hlist_bl_lock(&au_sbilist);
53392da6
AM
30957+}
30958+
30959+static inline void au_sbilist_unlock(void)
30960+{
8b6a4947 30961+ hlist_bl_unlock(&au_sbilist);
53392da6
AM
30962+}
30963+#define AuGFP_SBILIST GFP_ATOMIC
30964+#else
30965+AuStubVoid(au_sbilist_lock, void)
30966+AuStubVoid(au_sbilist_unlock, void)
30967+#define AuGFP_SBILIST GFP_NOFS
30968+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
30969+#else
30970+AuStubVoid(au_sbilist_init, void)
c1595e42
JR
30971+AuStubVoid(au_sbilist_add, struct super_block *sb)
30972+AuStubVoid(au_sbilist_del, struct super_block *sb)
53392da6
AM
30973+AuStubVoid(au_sbilist_lock, void)
30974+AuStubVoid(au_sbilist_unlock, void)
30975+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
30976+#endif
30977+
30978+/* ---------------------------------------------------------------------- */
30979+
1facf9fc 30980+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
30981+{
dece6358 30982+ /*
c1595e42 30983+ * This function is a dynamic '__init' function actually,
dece6358
AM
30984+ * so the tiny check for si_rwsem is unnecessary.
30985+ */
30986+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 30987+#ifdef CONFIG_DEBUG_FS
30988+ sbinfo->si_dbgaufs = NULL;
86dc4139 30989+ sbinfo->si_dbgaufs_plink = NULL;
1facf9fc 30990+ sbinfo->si_dbgaufs_xib = NULL;
30991+#ifdef CONFIG_AUFS_EXPORT
30992+ sbinfo->si_dbgaufs_xigen = NULL;
30993+#endif
30994+#endif
30995+}
30996+
30997+/* ---------------------------------------------------------------------- */
30998+
a2654f78
AM
30999+/* current->atomic_flags */
31000+/* this value should never corrupt the ones defined in linux/sched.h */
fbc438ed 31001+#define PFA_AUFS 0x10
a2654f78
AM
31002+
31003+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */
31004+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */
31005+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */
b752ccd1
AM
31006+
31007+static inline int si_pid_test(struct super_block *sb)
31008+{
a2654f78 31009+ return !!task_test_aufs(current);
b752ccd1
AM
31010+}
31011+
31012+static inline void si_pid_clr(struct super_block *sb)
31013+{
a2654f78
AM
31014+ AuDebugOn(!task_test_aufs(current));
31015+ task_clear_aufs(current);
b752ccd1
AM
31016+}
31017+
a2654f78
AM
31018+static inline void si_pid_set(struct super_block *sb)
31019+{
31020+ AuDebugOn(task_test_aufs(current));
31021+ task_set_aufs(current);
31022+}
febd17d6 31023+
b752ccd1
AM
31024+/* ---------------------------------------------------------------------- */
31025+
1facf9fc 31026+/* lock superblock. mainly for entry point functions */
8b6a4947
AM
31027+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem)
31028+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem)
31029+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem)
31030+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem)
31031+/*
31032+#define __si_read_trylock_nested(sb) \
31033+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem)
31034+#define __si_write_trylock_nested(sb) \
31035+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem)
31036+*/
31037+
31038+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem)
31039+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem)
31040+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem)
1facf9fc 31041+
dece6358
AM
31042+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
31043+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
31044+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
31045+
b752ccd1
AM
31046+static inline void si_noflush_read_lock(struct super_block *sb)
31047+{
31048+ __si_read_lock(sb);
31049+ si_pid_set(sb);
31050+}
31051+
31052+static inline int si_noflush_read_trylock(struct super_block *sb)
31053+{
076b876e
AM
31054+ int locked;
31055+
31056+ locked = __si_read_trylock(sb);
b752ccd1
AM
31057+ if (locked)
31058+ si_pid_set(sb);
31059+ return locked;
31060+}
31061+
31062+static inline void si_noflush_write_lock(struct super_block *sb)
31063+{
31064+ __si_write_lock(sb);
31065+ si_pid_set(sb);
31066+}
31067+
31068+static inline int si_noflush_write_trylock(struct super_block *sb)
31069+{
076b876e
AM
31070+ int locked;
31071+
31072+ locked = __si_write_trylock(sb);
b752ccd1
AM
31073+ if (locked)
31074+ si_pid_set(sb);
31075+ return locked;
31076+}
31077+
7e9cd9fe 31078+#if 0 /* reserved */
1facf9fc 31079+static inline int si_read_trylock(struct super_block *sb, int flags)
31080+{
31081+ if (au_ftest_lock(flags, FLUSH))
31082+ au_nwt_flush(&au_sbi(sb)->si_nowait);
31083+ return si_noflush_read_trylock(sb);
31084+}
e49829fe 31085+#endif
1facf9fc 31086+
b752ccd1
AM
31087+static inline void si_read_unlock(struct super_block *sb)
31088+{
31089+ si_pid_clr(sb);
31090+ __si_read_unlock(sb);
31091+}
31092+
7e9cd9fe 31093+#if 0 /* reserved */
1facf9fc 31094+static inline int si_write_trylock(struct super_block *sb, int flags)
31095+{
31096+ if (au_ftest_lock(flags, FLUSH))
31097+ au_nwt_flush(&au_sbi(sb)->si_nowait);
31098+ return si_noflush_write_trylock(sb);
31099+}
b752ccd1
AM
31100+#endif
31101+
31102+static inline void si_write_unlock(struct super_block *sb)
31103+{
31104+ si_pid_clr(sb);
31105+ __si_write_unlock(sb);
31106+}
31107+
7e9cd9fe 31108+#if 0 /* reserved */
b752ccd1
AM
31109+static inline void si_downgrade_lock(struct super_block *sb)
31110+{
31111+ __si_downgrade_lock(sb);
31112+}
31113+#endif
1facf9fc 31114+
31115+/* ---------------------------------------------------------------------- */
31116+
5afbbe0d 31117+static inline aufs_bindex_t au_sbbot(struct super_block *sb)
1facf9fc 31118+{
dece6358 31119+ SiMustAnyLock(sb);
5afbbe0d 31120+ return au_sbi(sb)->si_bbot;
1facf9fc 31121+}
31122+
31123+static inline unsigned int au_mntflags(struct super_block *sb)
31124+{
dece6358 31125+ SiMustAnyLock(sb);
1facf9fc 31126+ return au_sbi(sb)->si_mntflags;
31127+}
31128+
31129+static inline unsigned int au_sigen(struct super_block *sb)
31130+{
dece6358 31131+ SiMustAnyLock(sb);
1facf9fc 31132+ return au_sbi(sb)->si_generation;
31133+}
31134+
31135+static inline struct au_branch *au_sbr(struct super_block *sb,
31136+ aufs_bindex_t bindex)
31137+{
dece6358 31138+ SiMustAnyLock(sb);
1facf9fc 31139+ return au_sbi(sb)->si_branch[0 + bindex];
31140+}
31141+
acd2b654 31142+static inline loff_t au_xi_maxent(struct super_block *sb)
1facf9fc 31143+{
dece6358 31144+ SiMustAnyLock(sb);
acd2b654 31145+ return au_sbi(sb)->si_ximaxent;
1facf9fc 31146+}
31147+
31148+#endif /* __KERNEL__ */
31149+#endif /* __AUFS_SUPER_H__ */
7f207e10 31150diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
fbc438ed
JR
31151--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 08:00:00.000000000 +0800
31152+++ linux/fs/aufs/sysaufs.c 2019-07-11 21:21:54.382384486 +0800
062440b3 31153@@ -0,0 +1,93 @@
cd7a4cd9 31154+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31155+/*
ba1aed25 31156+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31157+ *
31158+ * This program, aufs is free software; you can redistribute it and/or modify
31159+ * it under the terms of the GNU General Public License as published by
31160+ * the Free Software Foundation; either version 2 of the License, or
31161+ * (at your option) any later version.
dece6358
AM
31162+ *
31163+ * This program is distributed in the hope that it will be useful,
31164+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31165+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31166+ * GNU General Public License for more details.
31167+ *
31168+ * You should have received a copy of the GNU General Public License
523b37e3 31169+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31170+ */
31171+
31172+/*
31173+ * sysfs interface and lifetime management
31174+ * they are necessary regardless sysfs is disabled.
31175+ */
31176+
1facf9fc 31177+#include <linux/random.h>
1facf9fc 31178+#include "aufs.h"
31179+
31180+unsigned long sysaufs_si_mask;
e49829fe 31181+struct kset *sysaufs_kset;
1facf9fc 31182+
31183+#define AuSiAttr(_name) { \
31184+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
31185+ .show = sysaufs_si_##_name, \
31186+}
31187+
31188+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
31189+struct attribute *sysaufs_si_attrs[] = {
31190+ &sysaufs_si_attr_xi_path.attr,
31191+ NULL,
31192+};
31193+
4a4d8108 31194+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 31195+ .show = sysaufs_si_show
31196+};
31197+
31198+static struct kobj_type au_sbi_ktype = {
31199+ .release = au_si_free,
31200+ .sysfs_ops = &au_sbi_ops,
31201+ .default_attrs = sysaufs_si_attrs
31202+};
31203+
31204+/* ---------------------------------------------------------------------- */
31205+
31206+int sysaufs_si_init(struct au_sbinfo *sbinfo)
31207+{
31208+ int err;
31209+
e49829fe 31210+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 31211+ /* cf. sysaufs_name() */
31212+ err = kobject_init_and_add
e49829fe 31213+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 31214+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
31215+
1facf9fc 31216+ return err;
31217+}
31218+
31219+void sysaufs_fin(void)
31220+{
e49829fe
JR
31221+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
31222+ kset_unregister(sysaufs_kset);
1facf9fc 31223+}
31224+
31225+int __init sysaufs_init(void)
31226+{
31227+ int err;
31228+
31229+ do {
31230+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
31231+ } while (!sysaufs_si_mask);
31232+
4a4d8108 31233+ err = -EINVAL;
e49829fe
JR
31234+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
31235+ if (unlikely(!sysaufs_kset))
4a4d8108 31236+ goto out;
e49829fe
JR
31237+ err = PTR_ERR(sysaufs_kset);
31238+ if (IS_ERR(sysaufs_kset))
1facf9fc 31239+ goto out;
e49829fe 31240+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
062440b3 31241+ if (unlikely(err))
e49829fe 31242+ kset_unregister(sysaufs_kset);
1facf9fc 31243+
4f0767ce 31244+out:
1facf9fc 31245+ return err;
31246+}
7f207e10 31247diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
fbc438ed
JR
31248--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 08:00:00.000000000 +0800
31249+++ linux/fs/aufs/sysaufs.h 2019-07-11 21:21:54.382384486 +0800
062440b3
AM
31250@@ -0,0 +1,102 @@
31251+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 31252+/*
ba1aed25 31253+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31254+ *
31255+ * This program, aufs is free software; you can redistribute it and/or modify
31256+ * it under the terms of the GNU General Public License as published by
31257+ * the Free Software Foundation; either version 2 of the License, or
31258+ * (at your option) any later version.
dece6358
AM
31259+ *
31260+ * This program is distributed in the hope that it will be useful,
31261+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31262+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31263+ * GNU General Public License for more details.
31264+ *
31265+ * You should have received a copy of the GNU General Public License
523b37e3 31266+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31267+ */
31268+
31269+/*
31270+ * sysfs interface and mount lifetime management
31271+ */
31272+
31273+#ifndef __SYSAUFS_H__
31274+#define __SYSAUFS_H__
31275+
31276+#ifdef __KERNEL__
31277+
1facf9fc 31278+#include <linux/sysfs.h>
1facf9fc 31279+#include "module.h"
31280+
dece6358
AM
31281+struct super_block;
31282+struct au_sbinfo;
31283+
1facf9fc 31284+struct sysaufs_si_attr {
31285+ struct attribute attr;
31286+ int (*show)(struct seq_file *seq, struct super_block *sb);
31287+};
31288+
31289+/* ---------------------------------------------------------------------- */
31290+
31291+/* sysaufs.c */
31292+extern unsigned long sysaufs_si_mask;
e49829fe 31293+extern struct kset *sysaufs_kset;
1facf9fc 31294+extern struct attribute *sysaufs_si_attrs[];
31295+int sysaufs_si_init(struct au_sbinfo *sbinfo);
31296+int __init sysaufs_init(void);
31297+void sysaufs_fin(void);
31298+
31299+/* ---------------------------------------------------------------------- */
31300+
31301+/* some people doesn't like to show a pointer in kernel */
31302+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
31303+{
31304+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
31305+}
31306+
31307+#define SysaufsSiNamePrefix "si_"
31308+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
31309+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
31310+{
31311+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
31312+ sysaufs_si_id(sbinfo));
31313+}
31314+
31315+struct au_branch;
31316+#ifdef CONFIG_SYSFS
31317+/* sysfs.c */
31318+extern struct attribute_group *sysaufs_attr_group;
31319+
31320+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
31321+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
31322+ char *buf);
076b876e
AM
31323+long au_brinfo_ioctl(struct file *file, unsigned long arg);
31324+#ifdef CONFIG_COMPAT
31325+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg);
31326+#endif
1facf9fc 31327+
31328+void sysaufs_br_init(struct au_branch *br);
31329+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
31330+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
31331+
31332+#define sysaufs_brs_init() do {} while (0)
31333+
31334+#else
31335+#define sysaufs_attr_group NULL
31336+
4a4d8108 31337+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
c1595e42
JR
31338+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj,
31339+ struct attribute *attr, char *buf)
4a4d8108
AM
31340+AuStubVoid(sysaufs_br_init, struct au_branch *br)
31341+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
31342+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 31343+
31344+static inline void sysaufs_brs_init(void)
31345+{
31346+ sysaufs_brs = 0;
31347+}
31348+
31349+#endif /* CONFIG_SYSFS */
31350+
31351+#endif /* __KERNEL__ */
31352+#endif /* __SYSAUFS_H__ */
7f207e10 31353diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
fbc438ed
JR
31354--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 08:00:00.000000000 +0800
31355+++ linux/fs/aufs/sysfs.c 2019-07-11 21:21:54.382384486 +0800
ba1aed25 31356@@ -0,0 +1,374 @@
cd7a4cd9 31357+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31358+/*
ba1aed25 31359+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31360+ *
31361+ * This program, aufs is free software; you can redistribute it and/or modify
31362+ * it under the terms of the GNU General Public License as published by
31363+ * the Free Software Foundation; either version 2 of the License, or
31364+ * (at your option) any later version.
dece6358
AM
31365+ *
31366+ * This program is distributed in the hope that it will be useful,
31367+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31368+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31369+ * GNU General Public License for more details.
31370+ *
31371+ * You should have received a copy of the GNU General Public License
523b37e3 31372+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31373+ */
31374+
31375+/*
31376+ * sysfs interface
31377+ */
31378+
076b876e 31379+#include <linux/compat.h>
1facf9fc 31380+#include <linux/seq_file.h>
1facf9fc 31381+#include "aufs.h"
31382+
4a4d8108
AM
31383+#ifdef CONFIG_AUFS_FS_MODULE
31384+/* this entry violates the "one line per file" policy of sysfs */
31385+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
31386+ char *buf)
31387+{
31388+ ssize_t err;
31389+ static char *conf =
31390+/* this file is generated at compiling */
31391+#include "conf.str"
31392+ ;
31393+
31394+ err = snprintf(buf, PAGE_SIZE, conf);
31395+ if (unlikely(err >= PAGE_SIZE))
31396+ err = -EFBIG;
31397+ return err;
31398+}
31399+
31400+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
31401+#endif
31402+
1facf9fc 31403+static struct attribute *au_attr[] = {
4a4d8108
AM
31404+#ifdef CONFIG_AUFS_FS_MODULE
31405+ &au_config_attr.attr,
31406+#endif
1facf9fc 31407+ NULL, /* need to NULL terminate the list of attributes */
31408+};
31409+
31410+static struct attribute_group sysaufs_attr_group_body = {
31411+ .attrs = au_attr
31412+};
31413+
31414+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
31415+
31416+/* ---------------------------------------------------------------------- */
31417+
31418+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
31419+{
31420+ int err;
31421+
dece6358
AM
31422+ SiMustAnyLock(sb);
31423+
1facf9fc 31424+ err = 0;
31425+ if (au_opt_test(au_mntflags(sb), XINO)) {
31426+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
31427+ seq_putc(seq, '\n');
31428+ }
31429+ return err;
31430+}
31431+
31432+/*
31433+ * the lifetime of branch is independent from the entry under sysfs.
31434+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
31435+ * unlinked.
31436+ */
31437+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
392086de 31438+ aufs_bindex_t bindex, int idx)
1facf9fc 31439+{
1e00d052 31440+ int err;
1facf9fc 31441+ struct path path;
31442+ struct dentry *root;
31443+ struct au_branch *br;
076b876e 31444+ au_br_perm_str_t perm;
1facf9fc 31445+
31446+ AuDbg("b%d\n", bindex);
31447+
1e00d052 31448+ err = 0;
1facf9fc 31449+ root = sb->s_root;
31450+ di_read_lock_parent(root, !AuLock_IR);
31451+ br = au_sbr(sb, bindex);
392086de
AM
31452+
31453+ switch (idx) {
31454+ case AuBrSysfs_BR:
31455+ path.mnt = au_br_mnt(br);
31456+ path.dentry = au_h_dptr(root, bindex);
79b8bda9
AM
31457+ err = au_seq_path(seq, &path);
31458+ if (!err) {
31459+ au_optstr_br_perm(&perm, br->br_perm);
31460+ seq_printf(seq, "=%s\n", perm.a);
31461+ }
392086de
AM
31462+ break;
31463+ case AuBrSysfs_BRID:
79b8bda9 31464+ seq_printf(seq, "%d\n", br->br_id);
392086de
AM
31465+ break;
31466+ }
076b876e 31467+ di_read_unlock(root, !AuLock_IR);
79b8bda9 31468+ if (unlikely(err || seq_has_overflowed(seq)))
076b876e 31469+ err = -E2BIG;
392086de 31470+
1e00d052 31471+ return err;
1facf9fc 31472+}
31473+
31474+/* ---------------------------------------------------------------------- */
31475+
31476+static struct seq_file *au_seq(char *p, ssize_t len)
31477+{
31478+ struct seq_file *seq;
31479+
31480+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
31481+ if (seq) {
31482+ /* mutex_init(&seq.lock); */
31483+ seq->buf = p;
31484+ seq->size = len;
31485+ return seq; /* success */
31486+ }
31487+
31488+ seq = ERR_PTR(-ENOMEM);
31489+ return seq;
31490+}
31491+
392086de
AM
31492+#define SysaufsBr_PREFIX "br"
31493+#define SysaufsBrid_PREFIX "brid"
1facf9fc 31494+
31495+/* todo: file size may exceed PAGE_SIZE */
31496+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 31497+ char *buf)
1facf9fc 31498+{
31499+ ssize_t err;
392086de 31500+ int idx;
1facf9fc 31501+ long l;
5afbbe0d 31502+ aufs_bindex_t bbot;
1facf9fc 31503+ struct au_sbinfo *sbinfo;
31504+ struct super_block *sb;
31505+ struct seq_file *seq;
31506+ char *name;
31507+ struct attribute **cattr;
31508+
31509+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
31510+ sb = sbinfo->si_sb;
1308ab2a 31511+
31512+ /*
31513+ * prevent a race condition between sysfs and aufs.
31514+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
31515+ * prohibits maintaining the sysfs entries.
31516+ * hew we acquire read lock after sysfs_get_active_two().
31517+ * on the other hand, the remount process may maintain the sysfs/aufs
31518+ * entries after acquiring write lock.
31519+ * it can cause a deadlock.
31520+ * simply we gave up processing read here.
31521+ */
31522+ err = -EBUSY;
31523+ if (unlikely(!si_noflush_read_trylock(sb)))
31524+ goto out;
1facf9fc 31525+
31526+ seq = au_seq(buf, PAGE_SIZE);
31527+ err = PTR_ERR(seq);
31528+ if (IS_ERR(seq))
1308ab2a 31529+ goto out_unlock;
1facf9fc 31530+
31531+ name = (void *)attr->name;
31532+ cattr = sysaufs_si_attrs;
31533+ while (*cattr) {
31534+ if (!strcmp(name, (*cattr)->name)) {
31535+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
31536+ ->show(seq, sb);
31537+ goto out_seq;
31538+ }
31539+ cattr++;
31540+ }
31541+
392086de
AM
31542+ if (!strncmp(name, SysaufsBrid_PREFIX,
31543+ sizeof(SysaufsBrid_PREFIX) - 1)) {
31544+ idx = AuBrSysfs_BRID;
31545+ name += sizeof(SysaufsBrid_PREFIX) - 1;
31546+ } else if (!strncmp(name, SysaufsBr_PREFIX,
31547+ sizeof(SysaufsBr_PREFIX) - 1)) {
31548+ idx = AuBrSysfs_BR;
1facf9fc 31549+ name += sizeof(SysaufsBr_PREFIX) - 1;
392086de
AM
31550+ } else
31551+ BUG();
31552+
31553+ err = kstrtol(name, 10, &l);
31554+ if (!err) {
5afbbe0d
AM
31555+ bbot = au_sbbot(sb);
31556+ if (l <= bbot)
392086de
AM
31557+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx);
31558+ else
31559+ err = -ENOENT;
1facf9fc 31560+ }
1facf9fc 31561+
4f0767ce 31562+out_seq:
1facf9fc 31563+ if (!err) {
31564+ err = seq->count;
31565+ /* sysfs limit */
31566+ if (unlikely(err == PAGE_SIZE))
31567+ err = -EFBIG;
31568+ }
9f237c51 31569+ au_kfree_rcu(seq);
4f0767ce 31570+out_unlock:
1facf9fc 31571+ si_read_unlock(sb);
4f0767ce 31572+out:
1facf9fc 31573+ return err;
31574+}
31575+
31576+/* ---------------------------------------------------------------------- */
31577+
076b876e
AM
31578+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg)
31579+{
31580+ int err;
31581+ int16_t brid;
5afbbe0d 31582+ aufs_bindex_t bindex, bbot;
076b876e
AM
31583+ size_t sz;
31584+ char *buf;
31585+ struct seq_file *seq;
31586+ struct au_branch *br;
31587+
31588+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d
AM
31589+ bbot = au_sbbot(sb);
31590+ err = bbot + 1;
076b876e
AM
31591+ if (!arg)
31592+ goto out;
31593+
31594+ err = -ENOMEM;
31595+ buf = (void *)__get_free_page(GFP_NOFS);
31596+ if (unlikely(!buf))
31597+ goto out;
31598+
31599+ seq = au_seq(buf, PAGE_SIZE);
31600+ err = PTR_ERR(seq);
31601+ if (IS_ERR(seq))
31602+ goto out_buf;
31603+
31604+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path);
5afbbe0d 31605+ for (bindex = 0; bindex <= bbot; bindex++, arg++) {
ba1aed25
AM
31606+ /* VERIFY_WRITE */
31607+ err = !access_ok(arg, sizeof(*arg));
076b876e
AM
31608+ if (unlikely(err))
31609+ break;
31610+
31611+ br = au_sbr(sb, bindex);
31612+ brid = br->br_id;
31613+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id));
31614+ err = __put_user(brid, &arg->id);
31615+ if (unlikely(err))
31616+ break;
31617+
31618+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm));
31619+ err = __put_user(br->br_perm, &arg->perm);
31620+ if (unlikely(err))
31621+ break;
31622+
79b8bda9
AM
31623+ err = au_seq_path(seq, &br->br_path);
31624+ if (unlikely(err))
31625+ break;
31626+ seq_putc(seq, '\0');
31627+ if (!seq_has_overflowed(seq)) {
076b876e
AM
31628+ err = copy_to_user(arg->path, seq->buf, seq->count);
31629+ seq->count = 0;
31630+ if (unlikely(err))
31631+ break;
31632+ } else {
31633+ err = -E2BIG;
31634+ goto out_seq;
31635+ }
31636+ }
31637+ if (unlikely(err))
31638+ err = -EFAULT;
31639+
31640+out_seq:
9f237c51 31641+ au_kfree_rcu(seq);
076b876e 31642+out_buf:
1c60b727 31643+ free_page((unsigned long)buf);
076b876e
AM
31644+out:
31645+ si_read_unlock(sb);
31646+ return err;
31647+}
31648+
31649+long au_brinfo_ioctl(struct file *file, unsigned long arg)
31650+{
2000de60 31651+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg);
076b876e
AM
31652+}
31653+
31654+#ifdef CONFIG_COMPAT
31655+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg)
31656+{
2000de60 31657+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg));
076b876e
AM
31658+}
31659+#endif
31660+
31661+/* ---------------------------------------------------------------------- */
31662+
1facf9fc 31663+void sysaufs_br_init(struct au_branch *br)
31664+{
392086de
AM
31665+ int i;
31666+ struct au_brsysfs *br_sysfs;
31667+ struct attribute *attr;
4a4d8108 31668+
392086de
AM
31669+ br_sysfs = br->br_sysfs;
31670+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31671+ attr = &br_sysfs->attr;
31672+ sysfs_attr_init(attr);
31673+ attr->name = br_sysfs->name;
cd7a4cd9 31674+ attr->mode = 0444;
392086de
AM
31675+ br_sysfs++;
31676+ }
1facf9fc 31677+}
31678+
31679+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
31680+{
31681+ struct au_branch *br;
31682+ struct kobject *kobj;
392086de
AM
31683+ struct au_brsysfs *br_sysfs;
31684+ int i;
5afbbe0d 31685+ aufs_bindex_t bbot;
1facf9fc 31686+
1facf9fc 31687+ if (!sysaufs_brs)
31688+ return;
31689+
31690+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31691+ bbot = au_sbbot(sb);
31692+ for (; bindex <= bbot; bindex++) {
1facf9fc 31693+ br = au_sbr(sb, bindex);
392086de
AM
31694+ br_sysfs = br->br_sysfs;
31695+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31696+ sysfs_remove_file(kobj, &br_sysfs->attr);
31697+ br_sysfs++;
31698+ }
1facf9fc 31699+ }
31700+}
31701+
31702+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
31703+{
392086de 31704+ int err, i;
5afbbe0d 31705+ aufs_bindex_t bbot;
1facf9fc 31706+ struct kobject *kobj;
31707+ struct au_branch *br;
392086de 31708+ struct au_brsysfs *br_sysfs;
1facf9fc 31709+
1facf9fc 31710+ if (!sysaufs_brs)
31711+ return;
31712+
31713+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31714+ bbot = au_sbbot(sb);
31715+ for (; bindex <= bbot; bindex++) {
1facf9fc 31716+ br = au_sbr(sb, bindex);
392086de
AM
31717+ br_sysfs = br->br_sysfs;
31718+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name),
31719+ SysaufsBr_PREFIX "%d", bindex);
31720+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name),
31721+ SysaufsBrid_PREFIX "%d", bindex);
31722+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31723+ err = sysfs_create_file(kobj, &br_sysfs->attr);
31724+ if (unlikely(err))
31725+ pr_warn("failed %s under sysfs(%d)\n",
31726+ br_sysfs->name, err);
31727+ br_sysfs++;
31728+ }
1facf9fc 31729+ }
31730+}
7f207e10 31731diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
fbc438ed
JR
31732--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 08:00:00.000000000 +0800
31733+++ linux/fs/aufs/sysrq.c 2019-07-11 21:21:54.382384486 +0800
062440b3 31734@@ -0,0 +1,160 @@
cd7a4cd9 31735+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31736+/*
ba1aed25 31737+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31738+ *
31739+ * This program, aufs is free software; you can redistribute it and/or modify
31740+ * it under the terms of the GNU General Public License as published by
31741+ * the Free Software Foundation; either version 2 of the License, or
31742+ * (at your option) any later version.
dece6358
AM
31743+ *
31744+ * This program is distributed in the hope that it will be useful,
31745+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31746+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31747+ * GNU General Public License for more details.
31748+ *
31749+ * You should have received a copy of the GNU General Public License
523b37e3 31750+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31751+ */
31752+
31753+/*
acd2b654 31754+ * magic sysrq handler
1facf9fc 31755+ */
31756+
1facf9fc 31757+/* #include <linux/sysrq.h> */
027c5e7a 31758+#include <linux/writeback.h>
1facf9fc 31759+#include "aufs.h"
31760+
31761+/* ---------------------------------------------------------------------- */
31762+
31763+static void sysrq_sb(struct super_block *sb)
31764+{
31765+ char *plevel;
31766+ struct au_sbinfo *sbinfo;
31767+ struct file *file;
8b6a4947
AM
31768+ struct hlist_bl_head *files;
31769+ struct hlist_bl_node *pos;
523b37e3 31770+ struct au_finfo *finfo;
1facf9fc 31771+
31772+ plevel = au_plevel;
31773+ au_plevel = KERN_WARNING;
1facf9fc 31774+
4a4d8108 31775+ /* since we define pr_fmt, call printk directly */
c06a8ce3
AM
31776+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str)
31777+
31778+ sbinfo = au_sbi(sb);
4a4d8108 31779+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
c06a8ce3 31780+ pr("superblock\n");
1facf9fc 31781+ au_dpri_sb(sb);
027c5e7a
AM
31782+
31783+#if 0
c06a8ce3 31784+ pr("root dentry\n");
1facf9fc 31785+ au_dpri_dentry(sb->s_root);
c06a8ce3 31786+ pr("root inode\n");
5527c038 31787+ au_dpri_inode(d_inode(sb->s_root));
027c5e7a
AM
31788+#endif
31789+
1facf9fc 31790+#if 0
027c5e7a
AM
31791+ do {
31792+ int err, i, j, ndentry;
31793+ struct au_dcsub_pages dpages;
31794+ struct au_dpage *dpage;
31795+
31796+ err = au_dpages_init(&dpages, GFP_ATOMIC);
31797+ if (unlikely(err))
31798+ break;
31799+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
31800+ if (!err)
31801+ for (i = 0; i < dpages.ndpage; i++) {
31802+ dpage = dpages.dpages + i;
31803+ ndentry = dpage->ndentry;
31804+ for (j = 0; j < ndentry; j++)
31805+ au_dpri_dentry(dpage->dentries[j]);
31806+ }
31807+ au_dpages_free(&dpages);
31808+ } while (0);
31809+#endif
31810+
31811+#if 1
31812+ {
31813+ struct inode *i;
076b876e 31814+
c06a8ce3 31815+ pr("isolated inode\n");
79b8bda9 31816+ spin_lock(&sb->s_inode_list_lock);
2cbb1c4b
JR
31817+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
31818+ spin_lock(&i->i_lock);
b4510431 31819+ if (1 || hlist_empty(&i->i_dentry))
027c5e7a 31820+ au_dpri_inode(i);
2cbb1c4b
JR
31821+ spin_unlock(&i->i_lock);
31822+ }
79b8bda9 31823+ spin_unlock(&sb->s_inode_list_lock);
027c5e7a 31824+ }
1facf9fc 31825+#endif
c06a8ce3 31826+ pr("files\n");
523b37e3 31827+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
31828+ hlist_bl_lock(files);
31829+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
4a4d8108 31830+ umode_t mode;
076b876e 31831+
523b37e3 31832+ file = finfo->fi_file;
c06a8ce3 31833+ mode = file_inode(file)->i_mode;
38d290e6 31834+ if (!special_file(mode))
1facf9fc 31835+ au_dpri_file(file);
523b37e3 31836+ }
8b6a4947 31837+ hlist_bl_unlock(files);
c06a8ce3 31838+ pr("done\n");
1facf9fc 31839+
c06a8ce3 31840+#undef pr
1facf9fc 31841+ au_plevel = plevel;
1facf9fc 31842+}
31843+
31844+/* ---------------------------------------------------------------------- */
31845+
31846+/* module parameter */
31847+static char *aufs_sysrq_key = "a";
cd7a4cd9 31848+module_param_named(sysrq, aufs_sysrq_key, charp, 0444);
1facf9fc 31849+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
31850+
0c5527e5 31851+static void au_sysrq(int key __maybe_unused)
1facf9fc 31852+{
1facf9fc 31853+ struct au_sbinfo *sbinfo;
8b6a4947 31854+ struct hlist_bl_node *pos;
1facf9fc 31855+
027c5e7a 31856+ lockdep_off();
53392da6 31857+ au_sbilist_lock();
8b6a4947 31858+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
1facf9fc 31859+ sysrq_sb(sbinfo->si_sb);
53392da6 31860+ au_sbilist_unlock();
027c5e7a 31861+ lockdep_on();
1facf9fc 31862+}
31863+
31864+static struct sysrq_key_op au_sysrq_op = {
31865+ .handler = au_sysrq,
31866+ .help_msg = "Aufs",
31867+ .action_msg = "Aufs",
31868+ .enable_mask = SYSRQ_ENABLE_DUMP
31869+};
31870+
31871+/* ---------------------------------------------------------------------- */
31872+
31873+int __init au_sysrq_init(void)
31874+{
31875+ int err;
31876+ char key;
31877+
31878+ err = -1;
31879+ key = *aufs_sysrq_key;
31880+ if ('a' <= key && key <= 'z')
31881+ err = register_sysrq_key(key, &au_sysrq_op);
31882+ if (unlikely(err))
4a4d8108 31883+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 31884+ return err;
31885+}
31886+
31887+void au_sysrq_fin(void)
31888+{
31889+ int err;
076b876e 31890+
1facf9fc 31891+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
31892+ if (unlikely(err))
4a4d8108 31893+ pr_err("err %d (ignored)\n", err);
1facf9fc 31894+}
7f207e10 31895diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
fbc438ed
JR
31896--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 08:00:00.000000000 +0800
31897+++ linux/fs/aufs/vdir.c 2019-07-11 21:21:54.382384486 +0800
eca801bf 31898@@ -0,0 +1,896 @@
cd7a4cd9 31899+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31900+/*
ba1aed25 31901+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 31902+ *
31903+ * This program, aufs is free software; you can redistribute it and/or modify
31904+ * it under the terms of the GNU General Public License as published by
31905+ * the Free Software Foundation; either version 2 of the License, or
31906+ * (at your option) any later version.
dece6358
AM
31907+ *
31908+ * This program is distributed in the hope that it will be useful,
31909+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31910+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31911+ * GNU General Public License for more details.
31912+ *
31913+ * You should have received a copy of the GNU General Public License
523b37e3 31914+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31915+ */
31916+
31917+/*
31918+ * virtual or vertical directory
31919+ */
31920+
eca801bf 31921+#include <linux/iversion.h>
1facf9fc 31922+#include "aufs.h"
31923+
dece6358 31924+static unsigned int calc_size(int nlen)
1facf9fc 31925+{
dece6358 31926+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 31927+}
31928+
31929+static int set_deblk_end(union au_vdir_deblk_p *p,
31930+ union au_vdir_deblk_p *deblk_end)
31931+{
31932+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
31933+ p->de->de_str.len = 0;
31934+ /* smp_mb(); */
31935+ return 0;
31936+ }
31937+ return -1; /* error */
31938+}
31939+
31940+/* returns true or false */
31941+static int is_deblk_end(union au_vdir_deblk_p *p,
31942+ union au_vdir_deblk_p *deblk_end)
31943+{
31944+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
31945+ return !p->de->de_str.len;
31946+ return 1;
31947+}
31948+
31949+static unsigned char *last_deblk(struct au_vdir *vdir)
31950+{
31951+ return vdir->vd_deblk[vdir->vd_nblk - 1];
31952+}
31953+
31954+/* ---------------------------------------------------------------------- */
31955+
79b8bda9 31956+/* estimate the appropriate size for name hash table */
1308ab2a 31957+unsigned int au_rdhash_est(loff_t sz)
31958+{
31959+ unsigned int n;
31960+
31961+ n = UINT_MAX;
31962+ sz >>= 10;
31963+ if (sz < n)
31964+ n = sz;
31965+ if (sz < AUFS_RDHASH_DEF)
31966+ n = AUFS_RDHASH_DEF;
4a4d8108 31967+ /* pr_info("n %u\n", n); */
1308ab2a 31968+ return n;
31969+}
31970+
1facf9fc 31971+/*
31972+ * the allocated memory has to be freed by
dece6358 31973+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 31974+ */
dece6358 31975+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 31976+{
1facf9fc 31977+ struct hlist_head *head;
dece6358 31978+ unsigned int u;
076b876e 31979+ size_t sz;
1facf9fc 31980+
076b876e
AM
31981+ sz = sizeof(*nhash->nh_head) * num_hash;
31982+ head = kmalloc(sz, gfp);
dece6358
AM
31983+ if (head) {
31984+ nhash->nh_num = num_hash;
31985+ nhash->nh_head = head;
31986+ for (u = 0; u < num_hash; u++)
1facf9fc 31987+ INIT_HLIST_HEAD(head++);
dece6358 31988+ return 0; /* success */
1facf9fc 31989+ }
1facf9fc 31990+
dece6358 31991+ return -ENOMEM;
1facf9fc 31992+}
31993+
dece6358
AM
31994+static void nhash_count(struct hlist_head *head)
31995+{
31996+#if 0
31997+ unsigned long n;
31998+ struct hlist_node *pos;
31999+
32000+ n = 0;
32001+ hlist_for_each(pos, head)
32002+ n++;
4a4d8108 32003+ pr_info("%lu\n", n);
dece6358
AM
32004+#endif
32005+}
32006+
32007+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 32008+{
c06a8ce3
AM
32009+ struct au_vdir_wh *pos;
32010+ struct hlist_node *node;
1facf9fc 32011+
c06a8ce3 32012+ hlist_for_each_entry_safe(pos, node, head, wh_hash)
9f237c51 32013+ au_kfree_rcu(pos);
1facf9fc 32014+}
32015+
dece6358 32016+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 32017+{
c06a8ce3
AM
32018+ struct au_vdir_dehstr *pos;
32019+ struct hlist_node *node;
1facf9fc 32020+
c06a8ce3 32021+ hlist_for_each_entry_safe(pos, node, head, hash)
1c60b727 32022+ au_cache_free_vdir_dehstr(pos);
1facf9fc 32023+}
32024+
dece6358
AM
32025+static void au_nhash_do_free(struct au_nhash *nhash,
32026+ void (*free)(struct hlist_head *head))
1facf9fc 32027+{
1308ab2a 32028+ unsigned int n;
1facf9fc 32029+ struct hlist_head *head;
1facf9fc 32030+
dece6358 32031+ n = nhash->nh_num;
1308ab2a 32032+ if (!n)
32033+ return;
32034+
dece6358 32035+ head = nhash->nh_head;
1308ab2a 32036+ while (n-- > 0) {
dece6358
AM
32037+ nhash_count(head);
32038+ free(head++);
1facf9fc 32039+ }
9f237c51 32040+ au_kfree_try_rcu(nhash->nh_head);
1facf9fc 32041+}
32042+
dece6358 32043+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 32044+{
dece6358
AM
32045+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
32046+}
1facf9fc 32047+
dece6358
AM
32048+static void au_nhash_de_free(struct au_nhash *delist)
32049+{
32050+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 32051+}
32052+
32053+/* ---------------------------------------------------------------------- */
32054+
32055+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
32056+ int limit)
32057+{
32058+ int num;
32059+ unsigned int u, n;
32060+ struct hlist_head *head;
c06a8ce3 32061+ struct au_vdir_wh *pos;
1facf9fc 32062+
32063+ num = 0;
32064+ n = whlist->nh_num;
32065+ head = whlist->nh_head;
1308ab2a 32066+ for (u = 0; u < n; u++, head++)
c06a8ce3
AM
32067+ hlist_for_each_entry(pos, head, wh_hash)
32068+ if (pos->wh_bindex == btgt && ++num > limit)
1facf9fc 32069+ return 1;
1facf9fc 32070+ return 0;
32071+}
32072+
32073+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 32074+ unsigned char *name,
1facf9fc 32075+ unsigned int len)
32076+{
dece6358
AM
32077+ unsigned int v;
32078+ /* const unsigned int magic_bit = 12; */
32079+
1308ab2a 32080+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
32081+
dece6358 32082+ v = 0;
f0c0a007
AM
32083+ if (len > 8)
32084+ len = 8;
dece6358
AM
32085+ while (len--)
32086+ v += *name++;
32087+ /* v = hash_long(v, magic_bit); */
32088+ v %= nhash->nh_num;
32089+ return nhash->nh_head + v;
32090+}
32091+
32092+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
32093+ int nlen)
32094+{
32095+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 32096+}
32097+
32098+/* returns found or not */
dece6358 32099+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 32100+{
32101+ struct hlist_head *head;
c06a8ce3 32102+ struct au_vdir_wh *pos;
1facf9fc 32103+ struct au_vdir_destr *str;
32104+
dece6358 32105+ head = au_name_hash(whlist, name, nlen);
c06a8ce3
AM
32106+ hlist_for_each_entry(pos, head, wh_hash) {
32107+ str = &pos->wh_str;
1facf9fc 32108+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
32109+ if (au_nhash_test_name(str, name, nlen))
32110+ return 1;
32111+ }
32112+ return 0;
32113+}
32114+
32115+/* returns found(true) or not */
32116+static int test_known(struct au_nhash *delist, char *name, int nlen)
32117+{
32118+ struct hlist_head *head;
c06a8ce3 32119+ struct au_vdir_dehstr *pos;
dece6358
AM
32120+ struct au_vdir_destr *str;
32121+
32122+ head = au_name_hash(delist, name, nlen);
c06a8ce3
AM
32123+ hlist_for_each_entry(pos, head, hash) {
32124+ str = pos->str;
dece6358
AM
32125+ AuDbg("%.*s\n", str->len, str->name);
32126+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 32127+ return 1;
32128+ }
32129+ return 0;
32130+}
32131+
dece6358
AM
32132+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
32133+ unsigned char d_type)
32134+{
32135+#ifdef CONFIG_AUFS_SHWH
32136+ wh->wh_ino = ino;
32137+ wh->wh_type = d_type;
32138+#endif
32139+}
32140+
32141+/* ---------------------------------------------------------------------- */
32142+
32143+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
32144+ unsigned int d_type, aufs_bindex_t bindex,
32145+ unsigned char shwh)
1facf9fc 32146+{
32147+ int err;
32148+ struct au_vdir_destr *str;
32149+ struct au_vdir_wh *wh;
32150+
dece6358 32151+ AuDbg("%.*s\n", nlen, name);
1308ab2a 32152+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
32153+
1facf9fc 32154+ err = -ENOMEM;
dece6358 32155+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 32156+ if (unlikely(!wh))
32157+ goto out;
32158+
32159+ err = 0;
32160+ wh->wh_bindex = bindex;
dece6358
AM
32161+ if (shwh)
32162+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 32163+ str = &wh->wh_str;
dece6358
AM
32164+ str->len = nlen;
32165+ memcpy(str->name, name, nlen);
32166+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 32167+ /* smp_mb(); */
32168+
4f0767ce 32169+out:
1facf9fc 32170+ return err;
32171+}
32172+
1facf9fc 32173+static int append_deblk(struct au_vdir *vdir)
32174+{
32175+ int err;
dece6358 32176+ unsigned long ul;
1facf9fc 32177+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32178+ union au_vdir_deblk_p p, deblk_end;
32179+ unsigned char **o;
32180+
32181+ err = -ENOMEM;
e2f27e51
AM
32182+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
32183+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32184+ if (unlikely(!o))
32185+ goto out;
32186+
32187+ vdir->vd_deblk = o;
32188+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
32189+ if (p.deblk) {
32190+ ul = vdir->vd_nblk++;
32191+ vdir->vd_deblk[ul] = p.deblk;
32192+ vdir->vd_last.ul = ul;
32193+ vdir->vd_last.p.deblk = p.deblk;
32194+ deblk_end.deblk = p.deblk + deblk_sz;
32195+ err = set_deblk_end(&p, &deblk_end);
32196+ }
32197+
4f0767ce 32198+out:
1facf9fc 32199+ return err;
32200+}
32201+
dece6358
AM
32202+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
32203+ unsigned int d_type, struct au_nhash *delist)
32204+{
32205+ int err;
32206+ unsigned int sz;
32207+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32208+ union au_vdir_deblk_p p, *room, deblk_end;
32209+ struct au_vdir_dehstr *dehstr;
32210+
32211+ p.deblk = last_deblk(vdir);
32212+ deblk_end.deblk = p.deblk + deblk_sz;
32213+ room = &vdir->vd_last.p;
32214+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
32215+ || !is_deblk_end(room, &deblk_end));
32216+
32217+ sz = calc_size(nlen);
32218+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
32219+ err = append_deblk(vdir);
32220+ if (unlikely(err))
32221+ goto out;
32222+
32223+ p.deblk = last_deblk(vdir);
32224+ deblk_end.deblk = p.deblk + deblk_sz;
32225+ /* smp_mb(); */
32226+ AuDebugOn(room->deblk != p.deblk);
32227+ }
32228+
32229+ err = -ENOMEM;
4a4d8108 32230+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
32231+ if (unlikely(!dehstr))
32232+ goto out;
32233+
32234+ dehstr->str = &room->de->de_str;
32235+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
32236+ room->de->de_ino = ino;
32237+ room->de->de_type = d_type;
32238+ room->de->de_str.len = nlen;
32239+ memcpy(room->de->de_str.name, name, nlen);
32240+
32241+ err = 0;
32242+ room->deblk += sz;
32243+ if (unlikely(set_deblk_end(room, &deblk_end)))
32244+ err = append_deblk(vdir);
32245+ /* smp_mb(); */
32246+
4f0767ce 32247+out:
dece6358
AM
32248+ return err;
32249+}
32250+
32251+/* ---------------------------------------------------------------------- */
32252+
1c60b727 32253+void au_vdir_free(struct au_vdir *vdir)
dece6358
AM
32254+{
32255+ unsigned char **deblk;
32256+
32257+ deblk = vdir->vd_deblk;
1c60b727 32258+ while (vdir->vd_nblk--)
9f237c51
AM
32259+ au_kfree_try_rcu(*deblk++);
32260+ au_kfree_try_rcu(vdir->vd_deblk);
1c60b727 32261+ au_cache_free_vdir(vdir);
dece6358
AM
32262+}
32263+
1308ab2a 32264+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 32265+{
32266+ struct au_vdir *vdir;
1308ab2a 32267+ struct super_block *sb;
1facf9fc 32268+ int err;
32269+
2000de60 32270+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32271+ SiMustAnyLock(sb);
32272+
1facf9fc 32273+ err = -ENOMEM;
32274+ vdir = au_cache_alloc_vdir();
32275+ if (unlikely(!vdir))
32276+ goto out;
32277+
32278+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
32279+ if (unlikely(!vdir->vd_deblk))
32280+ goto out_free;
32281+
32282+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 32283+ if (!vdir->vd_deblk_sz) {
79b8bda9 32284+ /* estimate the appropriate size for deblk */
1308ab2a 32285+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 32286+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 32287+ }
1facf9fc 32288+ vdir->vd_nblk = 0;
32289+ vdir->vd_version = 0;
32290+ vdir->vd_jiffy = 0;
32291+ err = append_deblk(vdir);
32292+ if (!err)
32293+ return vdir; /* success */
32294+
9f237c51 32295+ au_kfree_try_rcu(vdir->vd_deblk);
1facf9fc 32296+
4f0767ce 32297+out_free:
1c60b727 32298+ au_cache_free_vdir(vdir);
4f0767ce 32299+out:
1facf9fc 32300+ vdir = ERR_PTR(err);
32301+ return vdir;
32302+}
32303+
32304+static int reinit_vdir(struct au_vdir *vdir)
32305+{
32306+ int err;
32307+ union au_vdir_deblk_p p, deblk_end;
32308+
32309+ while (vdir->vd_nblk > 1) {
9f237c51 32310+ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]);
1facf9fc 32311+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
32312+ vdir->vd_nblk--;
32313+ }
32314+ p.deblk = vdir->vd_deblk[0];
32315+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
32316+ err = set_deblk_end(&p, &deblk_end);
32317+ /* keep vd_dblk_sz */
32318+ vdir->vd_last.ul = 0;
32319+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32320+ vdir->vd_version = 0;
32321+ vdir->vd_jiffy = 0;
32322+ /* smp_mb(); */
32323+ return err;
32324+}
32325+
32326+/* ---------------------------------------------------------------------- */
32327+
1facf9fc 32328+#define AuFillVdir_CALLED 1
32329+#define AuFillVdir_WHABLE (1 << 1)
dece6358 32330+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 32331+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
32332+#define au_fset_fillvdir(flags, name) \
32333+ do { (flags) |= AuFillVdir_##name; } while (0)
32334+#define au_fclr_fillvdir(flags, name) \
32335+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 32336+
dece6358
AM
32337+#ifndef CONFIG_AUFS_SHWH
32338+#undef AuFillVdir_SHWH
32339+#define AuFillVdir_SHWH 0
32340+#endif
32341+
1facf9fc 32342+struct fillvdir_arg {
392086de 32343+ struct dir_context ctx;
1facf9fc 32344+ struct file *file;
32345+ struct au_vdir *vdir;
dece6358
AM
32346+ struct au_nhash delist;
32347+ struct au_nhash whlist;
1facf9fc 32348+ aufs_bindex_t bindex;
32349+ unsigned int flags;
32350+ int err;
32351+};
32352+
392086de 32353+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen,
1facf9fc 32354+ loff_t offset __maybe_unused, u64 h_ino,
32355+ unsigned int d_type)
32356+{
392086de 32357+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx);
1facf9fc 32358+ char *name = (void *)__name;
32359+ struct super_block *sb;
1facf9fc 32360+ ino_t ino;
dece6358 32361+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 32362+
1facf9fc 32363+ arg->err = 0;
2000de60 32364+ sb = arg->file->f_path.dentry->d_sb;
1facf9fc 32365+ au_fset_fillvdir(arg->flags, CALLED);
32366+ /* smp_mb(); */
dece6358 32367+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 32368+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
32369+ if (test_known(&arg->delist, name, nlen)
32370+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
32371+ goto out; /* already exists or whiteouted */
1facf9fc 32372+
dece6358 32373+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
32374+ if (!arg->err) {
32375+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
32376+ d_type = DT_UNKNOWN;
dece6358
AM
32377+ arg->err = append_de(arg->vdir, name, nlen, ino,
32378+ d_type, &arg->delist);
4a4d8108 32379+ }
1facf9fc 32380+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
32381+ name += AUFS_WH_PFX_LEN;
dece6358
AM
32382+ nlen -= AUFS_WH_PFX_LEN;
32383+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
32384+ goto out; /* already whiteouted */
1facf9fc 32385+
acd2b654 32386+ ino = 0; /* just to suppress a warning */
dece6358
AM
32387+ if (shwh)
32388+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
32389+ &ino);
4a4d8108
AM
32390+ if (!arg->err) {
32391+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
32392+ d_type = DT_UNKNOWN;
1facf9fc 32393+ arg->err = au_nhash_append_wh
dece6358
AM
32394+ (&arg->whlist, name, nlen, ino, d_type,
32395+ arg->bindex, shwh);
4a4d8108 32396+ }
1facf9fc 32397+ }
32398+
4f0767ce 32399+out:
1facf9fc 32400+ if (!arg->err)
32401+ arg->vdir->vd_jiffy = jiffies;
32402+ /* smp_mb(); */
32403+ AuTraceErr(arg->err);
32404+ return arg->err;
32405+}
32406+
dece6358
AM
32407+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
32408+ struct au_nhash *whlist, struct au_nhash *delist)
32409+{
32410+#ifdef CONFIG_AUFS_SHWH
32411+ int err;
32412+ unsigned int nh, u;
32413+ struct hlist_head *head;
c06a8ce3
AM
32414+ struct au_vdir_wh *pos;
32415+ struct hlist_node *n;
dece6358
AM
32416+ char *p, *o;
32417+ struct au_vdir_destr *destr;
32418+
32419+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
32420+
32421+ err = -ENOMEM;
537831f9 32422+ o = p = (void *)__get_free_page(GFP_NOFS);
dece6358
AM
32423+ if (unlikely(!p))
32424+ goto out;
32425+
32426+ err = 0;
32427+ nh = whlist->nh_num;
32428+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
32429+ p += AUFS_WH_PFX_LEN;
32430+ for (u = 0; u < nh; u++) {
32431+ head = whlist->nh_head + u;
c06a8ce3
AM
32432+ hlist_for_each_entry_safe(pos, n, head, wh_hash) {
32433+ destr = &pos->wh_str;
dece6358
AM
32434+ memcpy(p, destr->name, destr->len);
32435+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
c06a8ce3 32436+ pos->wh_ino, pos->wh_type, delist);
dece6358
AM
32437+ if (unlikely(err))
32438+ break;
32439+ }
32440+ }
32441+
1c60b727 32442+ free_page((unsigned long)o);
dece6358 32443+
4f0767ce 32444+out:
dece6358
AM
32445+ AuTraceErr(err);
32446+ return err;
32447+#else
32448+ return 0;
32449+#endif
32450+}
32451+
1facf9fc 32452+static int au_do_read_vdir(struct fillvdir_arg *arg)
32453+{
32454+ int err;
dece6358 32455+ unsigned int rdhash;
1facf9fc 32456+ loff_t offset;
5afbbe0d 32457+ aufs_bindex_t bbot, bindex, btop;
dece6358 32458+ unsigned char shwh;
1facf9fc 32459+ struct file *hf, *file;
32460+ struct super_block *sb;
32461+
1facf9fc 32462+ file = arg->file;
2000de60 32463+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32464+ SiMustAnyLock(sb);
32465+
32466+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 32467+ if (!rdhash)
32468+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
32469+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
32470+ if (unlikely(err))
1facf9fc 32471+ goto out;
dece6358
AM
32472+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
32473+ if (unlikely(err))
1facf9fc 32474+ goto out_delist;
32475+
32476+ err = 0;
32477+ arg->flags = 0;
dece6358
AM
32478+ shwh = 0;
32479+ if (au_opt_test(au_mntflags(sb), SHWH)) {
32480+ shwh = 1;
32481+ au_fset_fillvdir(arg->flags, SHWH);
32482+ }
5afbbe0d
AM
32483+ btop = au_fbtop(file);
32484+ bbot = au_fbbot_dir(file);
32485+ for (bindex = btop; !err && bindex <= bbot; bindex++) {
4a4d8108 32486+ hf = au_hf_dir(file, bindex);
1facf9fc 32487+ if (!hf)
32488+ continue;
32489+
32490+ offset = vfsub_llseek(hf, 0, SEEK_SET);
32491+ err = offset;
32492+ if (unlikely(offset))
32493+ break;
32494+
32495+ arg->bindex = bindex;
32496+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358 32497+ if (shwh
5afbbe0d 32498+ || (bindex != bbot
dece6358 32499+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 32500+ au_fset_fillvdir(arg->flags, WHABLE);
32501+ do {
32502+ arg->err = 0;
32503+ au_fclr_fillvdir(arg->flags, CALLED);
32504+ /* smp_mb(); */
392086de 32505+ err = vfsub_iterate_dir(hf, &arg->ctx);
1facf9fc 32506+ if (err >= 0)
32507+ err = arg->err;
32508+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
392086de
AM
32509+
32510+ /*
32511+ * dir_relax() may be good for concurrency, but aufs should not
32512+ * use it since it will cause a lockdep problem.
32513+ */
1facf9fc 32514+ }
dece6358
AM
32515+
32516+ if (!err && shwh)
32517+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
32518+
32519+ au_nhash_wh_free(&arg->whlist);
1facf9fc 32520+
4f0767ce 32521+out_delist:
dece6358 32522+ au_nhash_de_free(&arg->delist);
4f0767ce 32523+out:
1facf9fc 32524+ return err;
32525+}
32526+
32527+static int read_vdir(struct file *file, int may_read)
32528+{
32529+ int err;
32530+ unsigned long expire;
32531+ unsigned char do_read;
392086de
AM
32532+ struct fillvdir_arg arg = {
32533+ .ctx = {
2000de60 32534+ .actor = fillvdir
392086de
AM
32535+ }
32536+ };
1facf9fc 32537+ struct inode *inode;
32538+ struct au_vdir *vdir, *allocated;
32539+
32540+ err = 0;
c06a8ce3 32541+ inode = file_inode(file);
1facf9fc 32542+ IMustLock(inode);
5afbbe0d 32543+ IiMustWriteLock(inode);
dece6358
AM
32544+ SiMustAnyLock(inode->i_sb);
32545+
1facf9fc 32546+ allocated = NULL;
32547+ do_read = 0;
32548+ expire = au_sbi(inode->i_sb)->si_rdcache;
32549+ vdir = au_ivdir(inode);
32550+ if (!vdir) {
32551+ do_read = 1;
1308ab2a 32552+ vdir = alloc_vdir(file);
1facf9fc 32553+ err = PTR_ERR(vdir);
32554+ if (IS_ERR(vdir))
32555+ goto out;
32556+ err = 0;
32557+ allocated = vdir;
32558+ } else if (may_read
be118d29 32559+ && (!inode_eq_iversion(inode, vdir->vd_version)
1facf9fc 32560+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
32561+ do_read = 1;
32562+ err = reinit_vdir(vdir);
32563+ if (unlikely(err))
32564+ goto out;
32565+ }
32566+
32567+ if (!do_read)
32568+ return 0; /* success */
32569+
32570+ arg.file = file;
32571+ arg.vdir = vdir;
32572+ err = au_do_read_vdir(&arg);
32573+ if (!err) {
392086de 32574+ /* file->f_pos = 0; */ /* todo: ctx->pos? */
be118d29 32575+ vdir->vd_version = inode_query_iversion(inode);
1facf9fc 32576+ vdir->vd_last.ul = 0;
32577+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32578+ if (allocated)
32579+ au_set_ivdir(inode, allocated);
32580+ } else if (allocated)
1c60b727 32581+ au_vdir_free(allocated);
1facf9fc 32582+
4f0767ce 32583+out:
1facf9fc 32584+ return err;
32585+}
32586+
32587+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
32588+{
32589+ int err, rerr;
32590+ unsigned long ul, n;
32591+ const unsigned int deblk_sz = src->vd_deblk_sz;
32592+
32593+ AuDebugOn(tgt->vd_nblk != 1);
32594+
32595+ err = -ENOMEM;
32596+ if (tgt->vd_nblk < src->vd_nblk) {
32597+ unsigned char **p;
32598+
e2f27e51
AM
32599+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
32600+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32601+ if (unlikely(!p))
32602+ goto out;
32603+ tgt->vd_deblk = p;
32604+ }
32605+
1308ab2a 32606+ if (tgt->vd_deblk_sz != deblk_sz) {
32607+ unsigned char *p;
32608+
32609+ tgt->vd_deblk_sz = deblk_sz;
e2f27e51
AM
32610+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS,
32611+ /*may_shrink*/1);
1308ab2a 32612+ if (unlikely(!p))
32613+ goto out;
32614+ tgt->vd_deblk[0] = p;
32615+ }
1facf9fc 32616+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 32617+ tgt->vd_version = src->vd_version;
32618+ tgt->vd_jiffy = src->vd_jiffy;
32619+
32620+ n = src->vd_nblk;
32621+ for (ul = 1; ul < n; ul++) {
dece6358
AM
32622+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
32623+ GFP_NOFS);
32624+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 32625+ goto out;
1308ab2a 32626+ tgt->vd_nblk++;
1facf9fc 32627+ }
1308ab2a 32628+ tgt->vd_nblk = n;
32629+ tgt->vd_last.ul = tgt->vd_last.ul;
32630+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
32631+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
32632+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 32633+ /* smp_mb(); */
32634+ return 0; /* success */
32635+
4f0767ce 32636+out:
1facf9fc 32637+ rerr = reinit_vdir(tgt);
32638+ BUG_ON(rerr);
32639+ return err;
32640+}
32641+
32642+int au_vdir_init(struct file *file)
32643+{
32644+ int err;
32645+ struct inode *inode;
32646+ struct au_vdir *vdir_cache, *allocated;
32647+
392086de 32648+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32649+ err = read_vdir(file, !file->f_pos);
32650+ if (unlikely(err))
32651+ goto out;
32652+
32653+ allocated = NULL;
32654+ vdir_cache = au_fvdir_cache(file);
32655+ if (!vdir_cache) {
1308ab2a 32656+ vdir_cache = alloc_vdir(file);
1facf9fc 32657+ err = PTR_ERR(vdir_cache);
32658+ if (IS_ERR(vdir_cache))
32659+ goto out;
32660+ allocated = vdir_cache;
32661+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
392086de 32662+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32663+ err = reinit_vdir(vdir_cache);
32664+ if (unlikely(err))
32665+ goto out;
32666+ } else
32667+ return 0; /* success */
32668+
c06a8ce3 32669+ inode = file_inode(file);
1facf9fc 32670+ err = copy_vdir(vdir_cache, au_ivdir(inode));
32671+ if (!err) {
be118d29 32672+ file->f_version = inode_query_iversion(inode);
1facf9fc 32673+ if (allocated)
32674+ au_set_fvdir_cache(file, allocated);
32675+ } else if (allocated)
1c60b727 32676+ au_vdir_free(allocated);
1facf9fc 32677+
4f0767ce 32678+out:
1facf9fc 32679+ return err;
32680+}
32681+
32682+static loff_t calc_offset(struct au_vdir *vdir)
32683+{
32684+ loff_t offset;
32685+ union au_vdir_deblk_p p;
32686+
32687+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
32688+ offset = vdir->vd_last.p.deblk - p.deblk;
32689+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
32690+ return offset;
32691+}
32692+
32693+/* returns true or false */
392086de 32694+static int seek_vdir(struct file *file, struct dir_context *ctx)
1facf9fc 32695+{
32696+ int valid;
32697+ unsigned int deblk_sz;
32698+ unsigned long ul, n;
32699+ loff_t offset;
32700+ union au_vdir_deblk_p p, deblk_end;
32701+ struct au_vdir *vdir_cache;
32702+
32703+ valid = 1;
32704+ vdir_cache = au_fvdir_cache(file);
32705+ offset = calc_offset(vdir_cache);
32706+ AuDbg("offset %lld\n", offset);
392086de 32707+ if (ctx->pos == offset)
1facf9fc 32708+ goto out;
32709+
32710+ vdir_cache->vd_last.ul = 0;
32711+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
392086de 32712+ if (!ctx->pos)
1facf9fc 32713+ goto out;
32714+
32715+ valid = 0;
32716+ deblk_sz = vdir_cache->vd_deblk_sz;
392086de 32717+ ul = div64_u64(ctx->pos, deblk_sz);
1facf9fc 32718+ AuDbg("ul %lu\n", ul);
32719+ if (ul >= vdir_cache->vd_nblk)
32720+ goto out;
32721+
32722+ n = vdir_cache->vd_nblk;
32723+ for (; ul < n; ul++) {
32724+ p.deblk = vdir_cache->vd_deblk[ul];
32725+ deblk_end.deblk = p.deblk + deblk_sz;
32726+ offset = ul;
32727+ offset *= deblk_sz;
392086de 32728+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) {
1facf9fc 32729+ unsigned int l;
32730+
32731+ l = calc_size(p.de->de_str.len);
32732+ offset += l;
32733+ p.deblk += l;
32734+ }
32735+ if (!is_deblk_end(&p, &deblk_end)) {
32736+ valid = 1;
32737+ vdir_cache->vd_last.ul = ul;
32738+ vdir_cache->vd_last.p = p;
32739+ break;
32740+ }
32741+ }
32742+
4f0767ce 32743+out:
1facf9fc 32744+ /* smp_mb(); */
b00004a5
AM
32745+ if (!valid)
32746+ AuDbg("valid %d\n", !valid);
1facf9fc 32747+ return valid;
32748+}
32749+
392086de 32750+int au_vdir_fill_de(struct file *file, struct dir_context *ctx)
1facf9fc 32751+{
1facf9fc 32752+ unsigned int l, deblk_sz;
32753+ union au_vdir_deblk_p deblk_end;
32754+ struct au_vdir *vdir_cache;
32755+ struct au_vdir_de *de;
32756+
392086de 32757+ if (!seek_vdir(file, ctx))
1facf9fc 32758+ return 0;
32759+
acd2b654 32760+ vdir_cache = au_fvdir_cache(file);
1facf9fc 32761+ deblk_sz = vdir_cache->vd_deblk_sz;
32762+ while (1) {
32763+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
32764+ deblk_end.deblk += deblk_sz;
32765+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
32766+ de = vdir_cache->vd_last.p.de;
32767+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
392086de 32768+ de->de_str.len, de->de_str.name, ctx->pos,
1facf9fc 32769+ (unsigned long)de->de_ino, de->de_type);
392086de
AM
32770+ if (unlikely(!dir_emit(ctx, de->de_str.name,
32771+ de->de_str.len, de->de_ino,
32772+ de->de_type))) {
1facf9fc 32773+ /* todo: ignore the error caused by udba? */
32774+ /* return err; */
32775+ return 0;
32776+ }
32777+
32778+ l = calc_size(de->de_str.len);
32779+ vdir_cache->vd_last.p.deblk += l;
392086de 32780+ ctx->pos += l;
1facf9fc 32781+ }
32782+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
32783+ vdir_cache->vd_last.ul++;
32784+ vdir_cache->vd_last.p.deblk
32785+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
392086de 32786+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul;
1facf9fc 32787+ continue;
32788+ }
32789+ break;
32790+ }
32791+
32792+ /* smp_mb(); */
32793+ return 0;
32794+}
7f207e10 32795diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
fbc438ed
JR
32796--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 08:00:00.000000000 +0800
32797+++ linux/fs/aufs/vfsub.c 2019-07-11 21:21:54.382384486 +0800
acd2b654 32798@@ -0,0 +1,902 @@
cd7a4cd9 32799+// SPDX-License-Identifier: GPL-2.0
1facf9fc 32800+/*
ba1aed25 32801+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 32802+ *
32803+ * This program, aufs is free software; you can redistribute it and/or modify
32804+ * it under the terms of the GNU General Public License as published by
32805+ * the Free Software Foundation; either version 2 of the License, or
32806+ * (at your option) any later version.
dece6358
AM
32807+ *
32808+ * This program is distributed in the hope that it will be useful,
32809+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
32810+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32811+ * GNU General Public License for more details.
32812+ *
32813+ * You should have received a copy of the GNU General Public License
523b37e3 32814+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 32815+ */
32816+
32817+/*
32818+ * sub-routines for VFS
32819+ */
32820+
8b6a4947 32821+#include <linux/mnt_namespace.h>
dece6358 32822+#include <linux/namei.h>
8cdd5066 32823+#include <linux/nsproxy.h>
dece6358
AM
32824+#include <linux/security.h>
32825+#include <linux/splice.h>
1facf9fc 32826+#include "aufs.h"
32827+
8cdd5066
JR
32828+#ifdef CONFIG_AUFS_BR_FUSE
32829+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb)
32830+{
8cdd5066
JR
32831+ if (!au_test_fuse(h_sb) || !au_userns)
32832+ return 0;
32833+
8b6a4947 32834+ return is_current_mnt_ns(mnt) ? 0 : -EACCES;
8cdd5066
JR
32835+}
32836+#endif
32837+
a2654f78
AM
32838+int vfsub_sync_filesystem(struct super_block *h_sb, int wait)
32839+{
32840+ int err;
32841+
32842+ lockdep_off();
32843+ down_read(&h_sb->s_umount);
32844+ err = __sync_filesystem(h_sb, wait);
32845+ up_read(&h_sb->s_umount);
32846+ lockdep_on();
32847+
32848+ return err;
32849+}
32850+
8cdd5066
JR
32851+/* ---------------------------------------------------------------------- */
32852+
1facf9fc 32853+int vfsub_update_h_iattr(struct path *h_path, int *did)
32854+{
32855+ int err;
32856+ struct kstat st;
32857+ struct super_block *h_sb;
32858+
32859+ /* for remote fs, leave work for its getattr or d_revalidate */
32860+ /* for bad i_attr fs, handle them in aufs_getattr() */
32861+ /* still some fs may acquire i_mutex. we need to skip them */
32862+ err = 0;
32863+ if (!did)
32864+ did = &err;
32865+ h_sb = h_path->dentry->d_sb;
32866+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
32867+ if (*did)
521ced18 32868+ err = vfsub_getattr(h_path, &st);
1facf9fc 32869+
32870+ return err;
32871+}
32872+
32873+/* ---------------------------------------------------------------------- */
32874+
4a4d8108 32875+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 32876+{
32877+ struct file *file;
32878+
b4510431 32879+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */,
7f207e10 32880+ current_cred());
2cbb1c4b
JR
32881+ if (!IS_ERR_OR_NULL(file)
32882+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
5527c038 32883+ i_readcount_inc(d_inode(path->dentry));
4a4d8108 32884+
1308ab2a 32885+ return file;
32886+}
32887+
1facf9fc 32888+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
32889+{
32890+ struct file *file;
32891+
2cbb1c4b 32892+ lockdep_off();
7f207e10 32893+ file = filp_open(path,
2cbb1c4b 32894+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 32895+ mode);
2cbb1c4b 32896+ lockdep_on();
1facf9fc 32897+ if (IS_ERR(file))
32898+ goto out;
32899+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
32900+
4f0767ce 32901+out:
1facf9fc 32902+ return file;
32903+}
32904+
b912730e
AM
32905+/*
32906+ * Ideally this function should call VFS:do_last() in order to keep all its
32907+ * checkings. But it is very hard for aufs to regenerate several VFS internal
32908+ * structure such as nameidata. This is a second (or third) best approach.
32909+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open().
32910+ */
32911+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 32912+ struct vfsub_aopen_args *args)
b912730e
AM
32913+{
32914+ int err;
acd2b654 32915+ struct au_branch *br = args->br;
b912730e
AM
32916+ struct file *file = args->file;
32917+ /* copied from linux/fs/namei.c:atomic_open() */
32918+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL;
32919+
32920+ IMustLock(dir);
32921+ AuDebugOn(!dir->i_op->atomic_open);
32922+
32923+ err = au_br_test_oflag(args->open_flag, br);
32924+ if (unlikely(err))
32925+ goto out;
32926+
acd2b654
AM
32927+ au_lcnt_inc(&br->br_nfiles);
32928+ file->f_path.dentry = DENTRY_NOT_SET;
32929+ file->f_path.mnt = au_br_mnt(br);
32930+ AuDbg("%ps\n", dir->i_op->atomic_open);
b912730e 32931+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag,
acd2b654
AM
32932+ args->create_mode);
32933+ if (unlikely(err < 0)) {
32934+ au_lcnt_dec(&br->br_nfiles);
b912730e 32935+ goto out;
acd2b654 32936+ }
b912730e 32937+
acd2b654
AM
32938+ /* temporary workaround for nfsv4 branch */
32939+ if (au_test_nfs(dir->i_sb))
32940+ nfs_mark_for_revalidate(dir);
b912730e 32941+
acd2b654
AM
32942+ if (file->f_mode & FMODE_CREATED)
32943+ fsnotify_create(dir, dentry);
32944+ if (!(file->f_mode & FMODE_OPENED)) {
32945+ au_lcnt_dec(&br->br_nfiles);
32946+ goto out;
b912730e
AM
32947+ }
32948+
acd2b654
AM
32949+ /* todo: call VFS:may_open() here */
32950+ /* todo: ima_file_check() too? */
32951+ if (!err && (args->open_flag & __FMODE_EXEC))
32952+ err = deny_write_access(file);
32953+ if (!err)
32954+ fsnotify_open(file);
32955+ else
32956+ au_lcnt_dec(&br->br_nfiles);
32957+ /* note that the file is created and still opened */
b912730e
AM
32958+
32959+out:
32960+ return err;
32961+}
32962+
1facf9fc 32963+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
32964+{
32965+ int err;
32966+
1facf9fc 32967+ err = kern_path(name, flags, path);
5527c038 32968+ if (!err && d_is_positive(path->dentry))
1facf9fc 32969+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
32970+ return err;
32971+}
32972+
febd17d6
JR
32973+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
32974+ struct dentry *parent, int len)
32975+{
32976+ struct path path = {
32977+ .mnt = NULL
32978+ };
32979+
32980+ path.dentry = lookup_one_len_unlocked(name, parent, len);
32981+ if (IS_ERR(path.dentry))
32982+ goto out;
32983+ if (d_is_positive(path.dentry))
32984+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
32985+
32986+out:
32987+ AuTraceErrPtr(path.dentry);
32988+ return path.dentry;
32989+}
32990+
1facf9fc 32991+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
32992+ int len)
32993+{
32994+ struct path path = {
32995+ .mnt = NULL
32996+ };
32997+
1308ab2a 32998+ /* VFS checks it too, but by WARN_ON_ONCE() */
5527c038 32999+ IMustLock(d_inode(parent));
1facf9fc 33000+
33001+ path.dentry = lookup_one_len(name, parent, len);
33002+ if (IS_ERR(path.dentry))
33003+ goto out;
5527c038 33004+ if (d_is_positive(path.dentry))
1facf9fc 33005+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
33006+
4f0767ce 33007+out:
4a4d8108 33008+ AuTraceErrPtr(path.dentry);
1facf9fc 33009+ return path.dentry;
33010+}
33011+
b4510431 33012+void vfsub_call_lkup_one(void *args)
2cbb1c4b 33013+{
b4510431
AM
33014+ struct vfsub_lkup_one_args *a = args;
33015+ *a->errp = vfsub_lkup_one(a->name, a->parent);
2cbb1c4b
JR
33016+}
33017+
1facf9fc 33018+/* ---------------------------------------------------------------------- */
33019+
33020+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
33021+ struct dentry *d2, struct au_hinode *hdir2)
33022+{
33023+ struct dentry *d;
33024+
2cbb1c4b 33025+ lockdep_off();
1facf9fc 33026+ d = lock_rename(d1, d2);
2cbb1c4b 33027+ lockdep_on();
4a4d8108 33028+ au_hn_suspend(hdir1);
1facf9fc 33029+ if (hdir1 != hdir2)
4a4d8108 33030+ au_hn_suspend(hdir2);
1facf9fc 33031+
33032+ return d;
33033+}
33034+
33035+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
33036+ struct dentry *d2, struct au_hinode *hdir2)
33037+{
4a4d8108 33038+ au_hn_resume(hdir1);
1facf9fc 33039+ if (hdir1 != hdir2)
4a4d8108 33040+ au_hn_resume(hdir2);
2cbb1c4b 33041+ lockdep_off();
1facf9fc 33042+ unlock_rename(d1, d2);
2cbb1c4b 33043+ lockdep_on();
1facf9fc 33044+}
33045+
33046+/* ---------------------------------------------------------------------- */
33047+
b4510431 33048+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
1facf9fc 33049+{
33050+ int err;
33051+ struct dentry *d;
33052+
33053+ IMustLock(dir);
33054+
33055+ d = path->dentry;
33056+ path->dentry = d->d_parent;
b752ccd1 33057+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 33058+ path->dentry = d;
33059+ if (unlikely(err))
33060+ goto out;
33061+
c1595e42 33062+ lockdep_off();
b4510431 33063+ err = vfs_create(dir, path->dentry, mode, want_excl);
c1595e42 33064+ lockdep_on();
1facf9fc 33065+ if (!err) {
33066+ struct path tmp = *path;
33067+ int did;
33068+
33069+ vfsub_update_h_iattr(&tmp, &did);
33070+ if (did) {
33071+ tmp.dentry = path->dentry->d_parent;
33072+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33073+ }
33074+ /*ignore*/
33075+ }
33076+
4f0767ce 33077+out:
1facf9fc 33078+ return err;
33079+}
33080+
33081+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
33082+{
33083+ int err;
33084+ struct dentry *d;
33085+
33086+ IMustLock(dir);
33087+
33088+ d = path->dentry;
33089+ path->dentry = d->d_parent;
b752ccd1 33090+ err = security_path_symlink(path, d, symname);
1facf9fc 33091+ path->dentry = d;
33092+ if (unlikely(err))
33093+ goto out;
33094+
c1595e42 33095+ lockdep_off();
1facf9fc 33096+ err = vfs_symlink(dir, path->dentry, symname);
c1595e42 33097+ lockdep_on();
1facf9fc 33098+ if (!err) {
33099+ struct path tmp = *path;
33100+ int did;
33101+
33102+ vfsub_update_h_iattr(&tmp, &did);
33103+ if (did) {
33104+ tmp.dentry = path->dentry->d_parent;
33105+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33106+ }
33107+ /*ignore*/
33108+ }
33109+
4f0767ce 33110+out:
1facf9fc 33111+ return err;
33112+}
33113+
33114+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
33115+{
33116+ int err;
33117+ struct dentry *d;
33118+
33119+ IMustLock(dir);
33120+
33121+ d = path->dentry;
33122+ path->dentry = d->d_parent;
027c5e7a 33123+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 33124+ path->dentry = d;
33125+ if (unlikely(err))
33126+ goto out;
33127+
c1595e42 33128+ lockdep_off();
1facf9fc 33129+ err = vfs_mknod(dir, path->dentry, mode, dev);
c1595e42 33130+ lockdep_on();
1facf9fc 33131+ if (!err) {
33132+ struct path tmp = *path;
33133+ int did;
33134+
33135+ vfsub_update_h_iattr(&tmp, &did);
33136+ if (did) {
33137+ tmp.dentry = path->dentry->d_parent;
33138+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33139+ }
33140+ /*ignore*/
33141+ }
33142+
4f0767ce 33143+out:
1facf9fc 33144+ return err;
33145+}
33146+
33147+static int au_test_nlink(struct inode *inode)
33148+{
33149+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
33150+
33151+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
33152+ || inode->i_nlink < link_max)
33153+ return 0;
33154+ return -EMLINK;
33155+}
33156+
523b37e3
AM
33157+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
33158+ struct inode **delegated_inode)
1facf9fc 33159+{
33160+ int err;
33161+ struct dentry *d;
33162+
33163+ IMustLock(dir);
33164+
5527c038 33165+ err = au_test_nlink(d_inode(src_dentry));
1facf9fc 33166+ if (unlikely(err))
33167+ return err;
33168+
b4510431 33169+ /* we don't call may_linkat() */
1facf9fc 33170+ d = path->dentry;
33171+ path->dentry = d->d_parent;
b752ccd1 33172+ err = security_path_link(src_dentry, path, d);
1facf9fc 33173+ path->dentry = d;
33174+ if (unlikely(err))
33175+ goto out;
33176+
2cbb1c4b 33177+ lockdep_off();
523b37e3 33178+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode);
2cbb1c4b 33179+ lockdep_on();
1facf9fc 33180+ if (!err) {
33181+ struct path tmp = *path;
33182+ int did;
33183+
33184+ /* fuse has different memory inode for the same inumber */
33185+ vfsub_update_h_iattr(&tmp, &did);
33186+ if (did) {
33187+ tmp.dentry = path->dentry->d_parent;
33188+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33189+ tmp.dentry = src_dentry;
33190+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33191+ }
33192+ /*ignore*/
33193+ }
33194+
4f0767ce 33195+out:
1facf9fc 33196+ return err;
33197+}
33198+
33199+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
523b37e3 33200+ struct inode *dir, struct path *path,
f2c43d5f 33201+ struct inode **delegated_inode, unsigned int flags)
1facf9fc 33202+{
33203+ int err;
33204+ struct path tmp = {
33205+ .mnt = path->mnt
33206+ };
33207+ struct dentry *d;
33208+
33209+ IMustLock(dir);
33210+ IMustLock(src_dir);
33211+
33212+ d = path->dentry;
33213+ path->dentry = d->d_parent;
33214+ tmp.dentry = src_dentry->d_parent;
38d290e6 33215+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0);
1facf9fc 33216+ path->dentry = d;
33217+ if (unlikely(err))
33218+ goto out;
33219+
2cbb1c4b 33220+ lockdep_off();
523b37e3 33221+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry,
f2c43d5f 33222+ delegated_inode, flags);
2cbb1c4b 33223+ lockdep_on();
1facf9fc 33224+ if (!err) {
33225+ int did;
33226+
33227+ tmp.dentry = d->d_parent;
33228+ vfsub_update_h_iattr(&tmp, &did);
33229+ if (did) {
33230+ tmp.dentry = src_dentry;
33231+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33232+ tmp.dentry = src_dentry->d_parent;
33233+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33234+ }
33235+ /*ignore*/
33236+ }
33237+
4f0767ce 33238+out:
1facf9fc 33239+ return err;
33240+}
33241+
33242+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
33243+{
33244+ int err;
33245+ struct dentry *d;
33246+
33247+ IMustLock(dir);
33248+
33249+ d = path->dentry;
33250+ path->dentry = d->d_parent;
b752ccd1 33251+ err = security_path_mkdir(path, d, mode);
1facf9fc 33252+ path->dentry = d;
33253+ if (unlikely(err))
33254+ goto out;
33255+
c1595e42 33256+ lockdep_off();
1facf9fc 33257+ err = vfs_mkdir(dir, path->dentry, mode);
c1595e42 33258+ lockdep_on();
1facf9fc 33259+ if (!err) {
33260+ struct path tmp = *path;
33261+ int did;
33262+
33263+ vfsub_update_h_iattr(&tmp, &did);
33264+ if (did) {
33265+ tmp.dentry = path->dentry->d_parent;
33266+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33267+ }
33268+ /*ignore*/
33269+ }
33270+
4f0767ce 33271+out:
1facf9fc 33272+ return err;
33273+}
33274+
33275+int vfsub_rmdir(struct inode *dir, struct path *path)
33276+{
33277+ int err;
33278+ struct dentry *d;
33279+
33280+ IMustLock(dir);
33281+
33282+ d = path->dentry;
33283+ path->dentry = d->d_parent;
b752ccd1 33284+ err = security_path_rmdir(path, d);
1facf9fc 33285+ path->dentry = d;
33286+ if (unlikely(err))
33287+ goto out;
33288+
2cbb1c4b 33289+ lockdep_off();
1facf9fc 33290+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 33291+ lockdep_on();
1facf9fc 33292+ if (!err) {
33293+ struct path tmp = {
33294+ .dentry = path->dentry->d_parent,
33295+ .mnt = path->mnt
33296+ };
33297+
33298+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33299+ }
33300+
4f0767ce 33301+out:
1facf9fc 33302+ return err;
33303+}
33304+
33305+/* ---------------------------------------------------------------------- */
33306+
9dbd164d 33307+/* todo: support mmap_sem? */
1facf9fc 33308+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33309+ loff_t *ppos)
33310+{
33311+ ssize_t err;
33312+
2cbb1c4b 33313+ lockdep_off();
1facf9fc 33314+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 33315+ lockdep_on();
1facf9fc 33316+ if (err >= 0)
33317+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33318+ return err;
33319+}
33320+
33321+/* todo: kernel_read()? */
33322+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33323+ loff_t *ppos)
33324+{
33325+ ssize_t err;
33326+ mm_segment_t oldfs;
b752ccd1
AM
33327+ union {
33328+ void *k;
33329+ char __user *u;
33330+ } buf;
1facf9fc 33331+
b752ccd1 33332+ buf.k = kbuf;
1facf9fc 33333+ oldfs = get_fs();
33334+ set_fs(KERNEL_DS);
b752ccd1 33335+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 33336+ set_fs(oldfs);
33337+ return err;
33338+}
33339+
33340+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33341+ loff_t *ppos)
33342+{
33343+ ssize_t err;
33344+
2cbb1c4b 33345+ lockdep_off();
1facf9fc 33346+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 33347+ lockdep_on();
1facf9fc 33348+ if (err >= 0)
33349+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33350+ return err;
33351+}
33352+
33353+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
33354+{
33355+ ssize_t err;
33356+ mm_segment_t oldfs;
b752ccd1
AM
33357+ union {
33358+ void *k;
33359+ const char __user *u;
33360+ } buf;
1facf9fc 33361+
b752ccd1 33362+ buf.k = kbuf;
1facf9fc 33363+ oldfs = get_fs();
33364+ set_fs(KERNEL_DS);
b752ccd1 33365+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 33366+ set_fs(oldfs);
33367+ return err;
33368+}
33369+
4a4d8108
AM
33370+int vfsub_flush(struct file *file, fl_owner_t id)
33371+{
33372+ int err;
33373+
33374+ err = 0;
523b37e3 33375+ if (file->f_op->flush) {
2000de60 33376+ if (!au_test_nfs(file->f_path.dentry->d_sb))
2cbb1c4b
JR
33377+ err = file->f_op->flush(file, id);
33378+ else {
33379+ lockdep_off();
33380+ err = file->f_op->flush(file, id);
33381+ lockdep_on();
33382+ }
4a4d8108
AM
33383+ if (!err)
33384+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
33385+ /*ignore*/
33386+ }
33387+ return err;
33388+}
33389+
392086de 33390+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx)
1facf9fc 33391+{
33392+ int err;
33393+
062440b3 33394+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 33395+
2cbb1c4b 33396+ lockdep_off();
392086de 33397+ err = iterate_dir(file, ctx);
2cbb1c4b 33398+ lockdep_on();
1facf9fc 33399+ if (err >= 0)
33400+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1c60b727 33401+
1facf9fc 33402+ return err;
33403+}
33404+
33405+long vfsub_splice_to(struct file *in, loff_t *ppos,
33406+ struct pipe_inode_info *pipe, size_t len,
33407+ unsigned int flags)
33408+{
33409+ long err;
33410+
2cbb1c4b 33411+ lockdep_off();
0fc653ad 33412+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 33413+ lockdep_on();
4a4d8108 33414+ file_accessed(in);
1facf9fc 33415+ if (err >= 0)
33416+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
33417+ return err;
33418+}
33419+
33420+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33421+ loff_t *ppos, size_t len, unsigned int flags)
33422+{
33423+ long err;
33424+
2cbb1c4b 33425+ lockdep_off();
0fc653ad 33426+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 33427+ lockdep_on();
1facf9fc 33428+ if (err >= 0)
33429+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
33430+ return err;
33431+}
33432+
53392da6
AM
33433+int vfsub_fsync(struct file *file, struct path *path, int datasync)
33434+{
33435+ int err;
33436+
33437+ /* file can be NULL */
33438+ lockdep_off();
33439+ err = vfs_fsync(file, datasync);
33440+ lockdep_on();
33441+ if (!err) {
33442+ if (!path) {
33443+ AuDebugOn(!file);
33444+ path = &file->f_path;
33445+ }
33446+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
33447+ }
33448+ return err;
33449+}
33450+
1facf9fc 33451+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
33452+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33453+ struct file *h_file)
33454+{
33455+ int err;
33456+ struct inode *h_inode;
c06a8ce3 33457+ struct super_block *h_sb;
1facf9fc 33458+
1facf9fc 33459+ if (!h_file) {
c06a8ce3
AM
33460+ err = vfsub_truncate(h_path, length);
33461+ goto out;
1facf9fc 33462+ }
33463+
5527c038 33464+ h_inode = d_inode(h_path->dentry);
c06a8ce3
AM
33465+ h_sb = h_inode->i_sb;
33466+ lockdep_off();
33467+ sb_start_write(h_sb);
33468+ lockdep_on();
1facf9fc 33469+ err = locks_verify_truncate(h_inode, h_file, length);
33470+ if (!err)
953406b4 33471+ err = security_path_truncate(h_path);
2cbb1c4b
JR
33472+ if (!err) {
33473+ lockdep_off();
1facf9fc 33474+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
33475+ lockdep_on();
33476+ }
c06a8ce3
AM
33477+ lockdep_off();
33478+ sb_end_write(h_sb);
33479+ lockdep_on();
1facf9fc 33480+
4f0767ce 33481+out:
1facf9fc 33482+ return err;
33483+}
33484+
33485+/* ---------------------------------------------------------------------- */
33486+
33487+struct au_vfsub_mkdir_args {
33488+ int *errp;
33489+ struct inode *dir;
33490+ struct path *path;
33491+ int mode;
33492+};
33493+
33494+static void au_call_vfsub_mkdir(void *args)
33495+{
33496+ struct au_vfsub_mkdir_args *a = args;
33497+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
33498+}
33499+
33500+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
33501+{
33502+ int err, do_sio, wkq_err;
33503+
33504+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33505+ if (!do_sio) {
33506+ lockdep_off();
1facf9fc 33507+ err = vfsub_mkdir(dir, path, mode);
c1595e42
JR
33508+ lockdep_on();
33509+ } else {
1facf9fc 33510+ struct au_vfsub_mkdir_args args = {
33511+ .errp = &err,
33512+ .dir = dir,
33513+ .path = path,
33514+ .mode = mode
33515+ };
33516+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
33517+ if (unlikely(wkq_err))
33518+ err = wkq_err;
33519+ }
33520+
33521+ return err;
33522+}
33523+
33524+struct au_vfsub_rmdir_args {
33525+ int *errp;
33526+ struct inode *dir;
33527+ struct path *path;
33528+};
33529+
33530+static void au_call_vfsub_rmdir(void *args)
33531+{
33532+ struct au_vfsub_rmdir_args *a = args;
33533+ *a->errp = vfsub_rmdir(a->dir, a->path);
33534+}
33535+
33536+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
33537+{
33538+ int err, do_sio, wkq_err;
33539+
33540+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33541+ if (!do_sio) {
33542+ lockdep_off();
1facf9fc 33543+ err = vfsub_rmdir(dir, path);
c1595e42
JR
33544+ lockdep_on();
33545+ } else {
1facf9fc 33546+ struct au_vfsub_rmdir_args args = {
33547+ .errp = &err,
33548+ .dir = dir,
33549+ .path = path
33550+ };
33551+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
33552+ if (unlikely(wkq_err))
33553+ err = wkq_err;
33554+ }
33555+
33556+ return err;
33557+}
33558+
33559+/* ---------------------------------------------------------------------- */
33560+
33561+struct notify_change_args {
33562+ int *errp;
33563+ struct path *path;
33564+ struct iattr *ia;
523b37e3 33565+ struct inode **delegated_inode;
1facf9fc 33566+};
33567+
33568+static void call_notify_change(void *args)
33569+{
33570+ struct notify_change_args *a = args;
33571+ struct inode *h_inode;
33572+
5527c038 33573+ h_inode = d_inode(a->path->dentry);
1facf9fc 33574+ IMustLock(h_inode);
33575+
33576+ *a->errp = -EPERM;
33577+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
c1595e42 33578+ lockdep_off();
523b37e3
AM
33579+ *a->errp = notify_change(a->path->dentry, a->ia,
33580+ a->delegated_inode);
c1595e42 33581+ lockdep_on();
1facf9fc 33582+ if (!*a->errp)
33583+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
33584+ }
33585+ AuTraceErr(*a->errp);
33586+}
33587+
523b37e3
AM
33588+int vfsub_notify_change(struct path *path, struct iattr *ia,
33589+ struct inode **delegated_inode)
1facf9fc 33590+{
33591+ int err;
33592+ struct notify_change_args args = {
523b37e3
AM
33593+ .errp = &err,
33594+ .path = path,
33595+ .ia = ia,
33596+ .delegated_inode = delegated_inode
1facf9fc 33597+ };
33598+
33599+ call_notify_change(&args);
33600+
33601+ return err;
33602+}
33603+
523b37e3
AM
33604+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
33605+ struct inode **delegated_inode)
1facf9fc 33606+{
33607+ int err, wkq_err;
33608+ struct notify_change_args args = {
523b37e3
AM
33609+ .errp = &err,
33610+ .path = path,
33611+ .ia = ia,
33612+ .delegated_inode = delegated_inode
1facf9fc 33613+ };
33614+
33615+ wkq_err = au_wkq_wait(call_notify_change, &args);
33616+ if (unlikely(wkq_err))
33617+ err = wkq_err;
33618+
33619+ return err;
33620+}
33621+
33622+/* ---------------------------------------------------------------------- */
33623+
33624+struct unlink_args {
33625+ int *errp;
33626+ struct inode *dir;
33627+ struct path *path;
523b37e3 33628+ struct inode **delegated_inode;
1facf9fc 33629+};
33630+
33631+static void call_unlink(void *args)
33632+{
33633+ struct unlink_args *a = args;
33634+ struct dentry *d = a->path->dentry;
33635+ struct inode *h_inode;
33636+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
c1595e42 33637+ && au_dcount(d) == 1);
1facf9fc 33638+
33639+ IMustLock(a->dir);
33640+
33641+ a->path->dentry = d->d_parent;
33642+ *a->errp = security_path_unlink(a->path, d);
33643+ a->path->dentry = d;
33644+ if (unlikely(*a->errp))
33645+ return;
33646+
33647+ if (!stop_sillyrename)
33648+ dget(d);
5527c038
JR
33649+ h_inode = NULL;
33650+ if (d_is_positive(d)) {
33651+ h_inode = d_inode(d);
027c5e7a 33652+ ihold(h_inode);
5527c038 33653+ }
1facf9fc 33654+
2cbb1c4b 33655+ lockdep_off();
523b37e3 33656+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode);
2cbb1c4b 33657+ lockdep_on();
1facf9fc 33658+ if (!*a->errp) {
33659+ struct path tmp = {
33660+ .dentry = d->d_parent,
33661+ .mnt = a->path->mnt
33662+ };
33663+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33664+ }
33665+
33666+ if (!stop_sillyrename)
33667+ dput(d);
33668+ if (h_inode)
33669+ iput(h_inode);
33670+
33671+ AuTraceErr(*a->errp);
33672+}
33673+
33674+/*
33675+ * @dir: must be locked.
33676+ * @dentry: target dentry.
33677+ */
523b37e3
AM
33678+int vfsub_unlink(struct inode *dir, struct path *path,
33679+ struct inode **delegated_inode, int force)
1facf9fc 33680+{
33681+ int err;
33682+ struct unlink_args args = {
523b37e3
AM
33683+ .errp = &err,
33684+ .dir = dir,
33685+ .path = path,
33686+ .delegated_inode = delegated_inode
1facf9fc 33687+ };
33688+
33689+ if (!force)
33690+ call_unlink(&args);
33691+ else {
33692+ int wkq_err;
33693+
33694+ wkq_err = au_wkq_wait(call_unlink, &args);
33695+ if (unlikely(wkq_err))
33696+ err = wkq_err;
33697+ }
33698+
33699+ return err;
33700+}
7f207e10 33701diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
fbc438ed
JR
33702--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 08:00:00.000000000 +0800
33703+++ linux/fs/aufs/vfsub.h 2019-07-11 21:21:54.382384486 +0800
eca801bf 33704@@ -0,0 +1,354 @@
062440b3 33705+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 33706+/*
ba1aed25 33707+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 33708+ *
33709+ * This program, aufs is free software; you can redistribute it and/or modify
33710+ * it under the terms of the GNU General Public License as published by
33711+ * the Free Software Foundation; either version 2 of the License, or
33712+ * (at your option) any later version.
dece6358
AM
33713+ *
33714+ * This program is distributed in the hope that it will be useful,
33715+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33716+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33717+ * GNU General Public License for more details.
33718+ *
33719+ * You should have received a copy of the GNU General Public License
523b37e3 33720+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 33721+ */
33722+
33723+/*
33724+ * sub-routines for VFS
33725+ */
33726+
33727+#ifndef __AUFS_VFSUB_H__
33728+#define __AUFS_VFSUB_H__
33729+
33730+#ifdef __KERNEL__
33731+
33732+#include <linux/fs.h>
b4510431 33733+#include <linux/mount.h>
8cdd5066 33734+#include <linux/posix_acl.h>
c1595e42 33735+#include <linux/xattr.h>
7f207e10 33736+#include "debug.h"
1facf9fc 33737+
7f207e10 33738+/* copied from linux/fs/internal.h */
2cbb1c4b 33739+/* todo: BAD approach!! */
c06a8ce3 33740+extern void __mnt_drop_write(struct vfsmount *);
acd2b654 33741+extern struct file *alloc_empty_file(int, const struct cred *);
7f207e10
AM
33742+
33743+/* ---------------------------------------------------------------------- */
1facf9fc 33744+
33745+/* lock subclass for lower inode */
33746+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
33747+/* reduce? gave up. */
33748+enum {
c1595e42 33749+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */
1facf9fc 33750+ AuLsc_I_PARENT, /* lower inode, parent first */
33751+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 33752+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 33753+ AuLsc_I_CHILD,
33754+ AuLsc_I_CHILD2,
33755+ AuLsc_I_End
33756+};
33757+
33758+/* to debug easier, do not make them inlined functions */
33759+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
febd17d6 33760+#define IMustLock(i) AuDebugOn(!inode_is_locked(i))
1facf9fc 33761+
33762+/* ---------------------------------------------------------------------- */
33763+
7f207e10
AM
33764+static inline void vfsub_drop_nlink(struct inode *inode)
33765+{
33766+ AuDebugOn(!inode->i_nlink);
33767+ drop_nlink(inode);
33768+}
33769+
027c5e7a
AM
33770+static inline void vfsub_dead_dir(struct inode *inode)
33771+{
33772+ AuDebugOn(!S_ISDIR(inode->i_mode));
33773+ inode->i_flags |= S_DEAD;
33774+ clear_nlink(inode);
33775+}
33776+
392086de
AM
33777+static inline int vfsub_native_ro(struct inode *inode)
33778+{
8b6a4947 33779+ return sb_rdonly(inode->i_sb)
392086de
AM
33780+ || IS_RDONLY(inode)
33781+ /* || IS_APPEND(inode) */
33782+ || IS_IMMUTABLE(inode);
33783+}
33784+
8cdd5066
JR
33785+#ifdef CONFIG_AUFS_BR_FUSE
33786+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb);
33787+#else
33788+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb);
33789+#endif
33790+
a2654f78
AM
33791+int vfsub_sync_filesystem(struct super_block *h_sb, int wait);
33792+
7f207e10
AM
33793+/* ---------------------------------------------------------------------- */
33794+
33795+int vfsub_update_h_iattr(struct path *h_path, int *did);
33796+struct file *vfsub_dentry_open(struct path *path, int flags);
33797+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
acd2b654 33798+struct au_branch;
b912730e 33799+struct vfsub_aopen_args {
acd2b654
AM
33800+ struct file *file;
33801+ unsigned int open_flag;
33802+ umode_t create_mode;
33803+ struct au_branch *br;
b912730e 33804+};
b912730e 33805+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 33806+ struct vfsub_aopen_args *args);
1facf9fc 33807+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
b4510431 33808+
febd17d6
JR
33809+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
33810+ struct dentry *parent, int len);
1facf9fc 33811+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
33812+ int len);
b4510431
AM
33813+
33814+struct vfsub_lkup_one_args {
33815+ struct dentry **errp;
33816+ struct qstr *name;
33817+ struct dentry *parent;
33818+};
33819+
33820+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
33821+ struct dentry *parent)
33822+{
33823+ return vfsub_lookup_one_len(name->name, parent, name->len);
33824+}
33825+
33826+void vfsub_call_lkup_one(void *args);
33827+
33828+/* ---------------------------------------------------------------------- */
33829+
33830+static inline int vfsub_mnt_want_write(struct vfsmount *mnt)
33831+{
33832+ int err;
076b876e 33833+
b4510431
AM
33834+ lockdep_off();
33835+ err = mnt_want_write(mnt);
33836+ lockdep_on();
33837+ return err;
33838+}
33839+
33840+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
33841+{
33842+ lockdep_off();
33843+ mnt_drop_write(mnt);
33844+ lockdep_on();
33845+}
1facf9fc 33846+
7e9cd9fe 33847+#if 0 /* reserved */
c06a8ce3
AM
33848+static inline void vfsub_mnt_drop_write_file(struct file *file)
33849+{
33850+ lockdep_off();
33851+ mnt_drop_write_file(file);
33852+ lockdep_on();
33853+}
7e9cd9fe 33854+#endif
c06a8ce3 33855+
1facf9fc 33856+/* ---------------------------------------------------------------------- */
33857+
33858+struct au_hinode;
33859+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
33860+ struct dentry *d2, struct au_hinode *hdir2);
33861+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
33862+ struct dentry *d2, struct au_hinode *hdir2);
33863+
537831f9
AM
33864+int vfsub_create(struct inode *dir, struct path *path, int mode,
33865+ bool want_excl);
1facf9fc 33866+int vfsub_symlink(struct inode *dir, struct path *path,
33867+ const char *symname);
33868+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
33869+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
523b37e3 33870+ struct path *path, struct inode **delegated_inode);
1facf9fc 33871+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
523b37e3 33872+ struct inode *hdir, struct path *path,
f2c43d5f 33873+ struct inode **delegated_inode, unsigned int flags);
1facf9fc 33874+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
33875+int vfsub_rmdir(struct inode *dir, struct path *path);
33876+
33877+/* ---------------------------------------------------------------------- */
33878+
33879+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33880+ loff_t *ppos);
33881+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33882+ loff_t *ppos);
33883+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33884+ loff_t *ppos);
33885+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
33886+ loff_t *ppos);
4a4d8108 33887+int vfsub_flush(struct file *file, fl_owner_t id);
392086de
AM
33888+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx);
33889+
c06a8ce3
AM
33890+static inline loff_t vfsub_f_size_read(struct file *file)
33891+{
33892+ return i_size_read(file_inode(file));
33893+}
33894+
4a4d8108
AM
33895+static inline unsigned int vfsub_file_flags(struct file *file)
33896+{
33897+ unsigned int flags;
33898+
33899+ spin_lock(&file->f_lock);
33900+ flags = file->f_flags;
33901+ spin_unlock(&file->f_lock);
33902+
33903+ return flags;
33904+}
1308ab2a 33905+
f0c0a007
AM
33906+static inline int vfsub_file_execed(struct file *file)
33907+{
33908+ /* todo: direct access f_flags */
33909+ return !!(vfsub_file_flags(file) & __FMODE_EXEC);
33910+}
33911+
7e9cd9fe 33912+#if 0 /* reserved */
1facf9fc 33913+static inline void vfsub_file_accessed(struct file *h_file)
33914+{
33915+ file_accessed(h_file);
33916+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
33917+}
7e9cd9fe 33918+#endif
1facf9fc 33919+
79b8bda9 33920+#if 0 /* reserved */
1facf9fc 33921+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
33922+ struct dentry *h_dentry)
33923+{
33924+ struct path h_path = {
33925+ .dentry = h_dentry,
33926+ .mnt = h_mnt
33927+ };
92d182d2 33928+ touch_atime(&h_path);
1facf9fc 33929+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
33930+}
79b8bda9 33931+#endif
1facf9fc 33932+
cd7a4cd9
AM
33933+static inline int vfsub_update_time(struct inode *h_inode,
33934+ struct timespec64 *ts, int flags)
0c3ec466 33935+{
5afbbe0d 33936+ return update_time(h_inode, ts, flags);
0c3ec466
AM
33937+ /* no vfsub_update_h_iattr() since we don't have struct path */
33938+}
33939+
8cdd5066
JR
33940+#ifdef CONFIG_FS_POSIX_ACL
33941+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode)
33942+{
33943+ int err;
33944+
33945+ err = posix_acl_chmod(h_inode, h_mode);
33946+ if (err == -EOPNOTSUPP)
33947+ err = 0;
33948+ return err;
33949+}
33950+#else
33951+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode);
33952+#endif
33953+
4a4d8108
AM
33954+long vfsub_splice_to(struct file *in, loff_t *ppos,
33955+ struct pipe_inode_info *pipe, size_t len,
33956+ unsigned int flags);
33957+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33958+ loff_t *ppos, size_t len, unsigned int flags);
c06a8ce3
AM
33959+
33960+static inline long vfsub_truncate(struct path *path, loff_t length)
33961+{
33962+ long err;
076b876e 33963+
c06a8ce3
AM
33964+ lockdep_off();
33965+ err = vfs_truncate(path, length);
33966+ lockdep_on();
33967+ return err;
33968+}
33969+
4a4d8108
AM
33970+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33971+ struct file *h_file);
53392da6 33972+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 33973+
521ced18
JR
33974+/*
33975+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such
33976+ * ioctl.
33977+ */
9f237c51
AM
33978+static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst,
33979+ loff_t len)
521ced18 33980+{
9f237c51 33981+ loff_t err;
521ced18
JR
33982+
33983+ lockdep_off();
9f237c51 33984+ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0);
521ced18
JR
33985+ lockdep_on();
33986+
33987+ return err;
33988+}
33989+
33990+/* copy_file_range(2) is a systemcall */
33991+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos,
33992+ struct file *dst, loff_t dst_pos,
33993+ size_t len, unsigned int flags)
33994+{
33995+ ssize_t ssz;
33996+
33997+ lockdep_off();
33998+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags);
33999+ lockdep_on();
34000+
34001+ return ssz;
34002+}
34003+
1facf9fc 34004+/* ---------------------------------------------------------------------- */
34005+
34006+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
34007+{
34008+ loff_t err;
34009+
2cbb1c4b 34010+ lockdep_off();
1facf9fc 34011+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 34012+ lockdep_on();
1facf9fc 34013+ return err;
34014+}
34015+
34016+/* ---------------------------------------------------------------------- */
34017+
4a4d8108
AM
34018+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
34019+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
523b37e3
AM
34020+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
34021+ struct inode **delegated_inode);
34022+int vfsub_notify_change(struct path *path, struct iattr *ia,
34023+ struct inode **delegated_inode);
34024+int vfsub_unlink(struct inode *dir, struct path *path,
34025+ struct inode **delegated_inode, int force);
4a4d8108 34026+
521ced18
JR
34027+static inline int vfsub_getattr(const struct path *path, struct kstat *st)
34028+{
34029+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
34030+}
34031+
c1595e42
JR
34032+/* ---------------------------------------------------------------------- */
34033+
34034+static inline int vfsub_setxattr(struct dentry *dentry, const char *name,
34035+ const void *value, size_t size, int flags)
34036+{
34037+ int err;
34038+
34039+ lockdep_off();
34040+ err = vfs_setxattr(dentry, name, value, size, flags);
34041+ lockdep_on();
34042+
34043+ return err;
34044+}
34045+
34046+static inline int vfsub_removexattr(struct dentry *dentry, const char *name)
34047+{
34048+ int err;
34049+
34050+ lockdep_off();
34051+ err = vfs_removexattr(dentry, name);
34052+ lockdep_on();
34053+
34054+ return err;
34055+}
34056+
1facf9fc 34057+#endif /* __KERNEL__ */
34058+#endif /* __AUFS_VFSUB_H__ */
7f207e10 34059diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
fbc438ed
JR
34060--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 08:00:00.000000000 +0800
34061+++ linux/fs/aufs/wbr_policy.c 2019-07-11 21:21:54.382384486 +0800
cd7a4cd9
AM
34062@@ -0,0 +1,830 @@
34063+// SPDX-License-Identifier: GPL-2.0
1facf9fc 34064+/*
ba1aed25 34065+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 34066+ *
34067+ * This program, aufs is free software; you can redistribute it and/or modify
34068+ * it under the terms of the GNU General Public License as published by
34069+ * the Free Software Foundation; either version 2 of the License, or
34070+ * (at your option) any later version.
dece6358
AM
34071+ *
34072+ * This program is distributed in the hope that it will be useful,
34073+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34074+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34075+ * GNU General Public License for more details.
34076+ *
34077+ * You should have received a copy of the GNU General Public License
523b37e3 34078+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34079+ */
34080+
34081+/*
34082+ * policies for selecting one among multiple writable branches
34083+ */
34084+
34085+#include <linux/statfs.h>
34086+#include "aufs.h"
34087+
34088+/* subset of cpup_attr() */
34089+static noinline_for_stack
34090+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
34091+{
34092+ int err, sbits;
34093+ struct iattr ia;
34094+ struct inode *h_isrc;
34095+
5527c038 34096+ h_isrc = d_inode(h_src);
1facf9fc 34097+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
34098+ ia.ia_mode = h_isrc->i_mode;
34099+ ia.ia_uid = h_isrc->i_uid;
34100+ ia.ia_gid = h_isrc->i_gid;
34101+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
5527c038 34102+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags);
523b37e3
AM
34103+ /* no delegation since it is just created */
34104+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 34105+
34106+ /* is this nfs only? */
34107+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
34108+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
34109+ ia.ia_mode = h_isrc->i_mode;
523b37e3 34110+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 34111+ }
34112+
34113+ return err;
34114+}
34115+
34116+#define AuCpdown_PARENT_OPQ 1
34117+#define AuCpdown_WHED (1 << 1)
34118+#define AuCpdown_MADE_DIR (1 << 2)
34119+#define AuCpdown_DIROPQ (1 << 3)
34120+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
34121+#define au_fset_cpdown(flags, name) \
34122+ do { (flags) |= AuCpdown_##name; } while (0)
34123+#define au_fclr_cpdown(flags, name) \
34124+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 34125+
1facf9fc 34126+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
c2b27bf2 34127+ unsigned int *flags)
1facf9fc 34128+{
34129+ int err;
34130+ struct dentry *opq_dentry;
34131+
34132+ opq_dentry = au_diropq_create(dentry, bdst);
34133+ err = PTR_ERR(opq_dentry);
34134+ if (IS_ERR(opq_dentry))
34135+ goto out;
34136+ dput(opq_dentry);
c2b27bf2 34137+ au_fset_cpdown(*flags, DIROPQ);
1facf9fc 34138+
4f0767ce 34139+out:
1facf9fc 34140+ return err;
34141+}
34142+
34143+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
34144+ struct inode *dir, aufs_bindex_t bdst)
34145+{
34146+ int err;
34147+ struct path h_path;
34148+ struct au_branch *br;
34149+
34150+ br = au_sbr(dentry->d_sb, bdst);
34151+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
34152+ err = PTR_ERR(h_path.dentry);
34153+ if (IS_ERR(h_path.dentry))
34154+ goto out;
34155+
34156+ err = 0;
5527c038 34157+ if (d_is_positive(h_path.dentry)) {
86dc4139 34158+ h_path.mnt = au_br_mnt(br);
1facf9fc 34159+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
34160+ dentry);
34161+ }
34162+ dput(h_path.dentry);
34163+
4f0767ce 34164+out:
1facf9fc 34165+ return err;
34166+}
34167+
34168+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 34169+ struct au_pin *pin,
1facf9fc 34170+ struct dentry *h_parent, void *arg)
34171+{
34172+ int err, rerr;
5afbbe0d 34173+ aufs_bindex_t bopq, btop;
1facf9fc 34174+ struct path h_path;
34175+ struct dentry *parent;
34176+ struct inode *h_dir, *h_inode, *inode, *dir;
c2b27bf2 34177+ unsigned int *flags = arg;
1facf9fc 34178+
5afbbe0d 34179+ btop = au_dbtop(dentry);
1facf9fc 34180+ /* dentry is di-locked */
34181+ parent = dget_parent(dentry);
5527c038
JR
34182+ dir = d_inode(parent);
34183+ h_dir = d_inode(h_parent);
1facf9fc 34184+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
34185+ IMustLock(h_dir);
34186+
86dc4139 34187+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
1facf9fc 34188+ if (unlikely(err < 0))
34189+ goto out;
34190+ h_path.dentry = au_h_dptr(dentry, bdst);
34191+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
cd7a4cd9 34192+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755);
1facf9fc 34193+ if (unlikely(err))
34194+ goto out_put;
c2b27bf2 34195+ au_fset_cpdown(*flags, MADE_DIR);
1facf9fc 34196+
1facf9fc 34197+ bopq = au_dbdiropq(dentry);
c2b27bf2
AM
34198+ au_fclr_cpdown(*flags, WHED);
34199+ au_fclr_cpdown(*flags, DIROPQ);
1facf9fc 34200+ if (au_dbwh(dentry) == bdst)
c2b27bf2
AM
34201+ au_fset_cpdown(*flags, WHED);
34202+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst)
34203+ au_fset_cpdown(*flags, PARENT_OPQ);
5527c038 34204+ h_inode = d_inode(h_path.dentry);
febd17d6 34205+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
c2b27bf2
AM
34206+ if (au_ftest_cpdown(*flags, WHED)) {
34207+ err = au_cpdown_dir_opq(dentry, bdst, flags);
1facf9fc 34208+ if (unlikely(err)) {
febd17d6 34209+ inode_unlock(h_inode);
1facf9fc 34210+ goto out_dir;
34211+ }
34212+ }
34213+
5afbbe0d 34214+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop));
febd17d6 34215+ inode_unlock(h_inode);
1facf9fc 34216+ if (unlikely(err))
34217+ goto out_opq;
34218+
c2b27bf2 34219+ if (au_ftest_cpdown(*flags, WHED)) {
1facf9fc 34220+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
34221+ if (unlikely(err))
34222+ goto out_opq;
34223+ }
34224+
5527c038 34225+ inode = d_inode(dentry);
5afbbe0d
AM
34226+ if (au_ibbot(inode) < bdst)
34227+ au_set_ibbot(inode, bdst);
1facf9fc 34228+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
34229+ au_hi_flags(inode, /*isdir*/1));
076b876e 34230+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0);
1facf9fc 34231+ goto out; /* success */
34232+
34233+ /* revert */
4f0767ce 34234+out_opq:
c2b27bf2 34235+ if (au_ftest_cpdown(*flags, DIROPQ)) {
febd17d6 34236+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 34237+ rerr = au_diropq_remove(dentry, bdst);
febd17d6 34238+ inode_unlock(h_inode);
1facf9fc 34239+ if (unlikely(rerr)) {
523b37e3
AM
34240+ AuIOErr("failed removing diropq for %pd b%d (%d)\n",
34241+ dentry, bdst, rerr);
1facf9fc 34242+ err = -EIO;
34243+ goto out;
34244+ }
34245+ }
4f0767ce 34246+out_dir:
c2b27bf2 34247+ if (au_ftest_cpdown(*flags, MADE_DIR)) {
1facf9fc 34248+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
34249+ if (unlikely(rerr)) {
523b37e3
AM
34250+ AuIOErr("failed removing %pd b%d (%d)\n",
34251+ dentry, bdst, rerr);
1facf9fc 34252+ err = -EIO;
34253+ }
34254+ }
4f0767ce 34255+out_put:
1facf9fc 34256+ au_set_h_dptr(dentry, bdst, NULL);
5afbbe0d
AM
34257+ if (au_dbbot(dentry) == bdst)
34258+ au_update_dbbot(dentry);
4f0767ce 34259+out:
1facf9fc 34260+ dput(parent);
34261+ return err;
34262+}
34263+
34264+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
34265+{
34266+ int err;
c2b27bf2 34267+ unsigned int flags;
1facf9fc 34268+
c2b27bf2
AM
34269+ flags = 0;
34270+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags);
1facf9fc 34271+
34272+ return err;
34273+}
34274+
34275+/* ---------------------------------------------------------------------- */
34276+
34277+/* policies for create */
34278+
c2b27bf2 34279+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
4a4d8108
AM
34280+{
34281+ int err, i, j, ndentry;
34282+ aufs_bindex_t bopq;
34283+ struct au_dcsub_pages dpages;
34284+ struct au_dpage *dpage;
34285+ struct dentry **dentries, *parent, *d;
34286+
34287+ err = au_dpages_init(&dpages, GFP_NOFS);
34288+ if (unlikely(err))
34289+ goto out;
34290+ parent = dget_parent(dentry);
027c5e7a 34291+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
34292+ if (unlikely(err))
34293+ goto out_free;
34294+
34295+ err = bindex;
34296+ for (i = 0; i < dpages.ndpage; i++) {
34297+ dpage = dpages.dpages + i;
34298+ dentries = dpage->dentries;
34299+ ndentry = dpage->ndentry;
34300+ for (j = 0; j < ndentry; j++) {
34301+ d = dentries[j];
34302+ di_read_lock_parent2(d, !AuLock_IR);
34303+ bopq = au_dbdiropq(d);
34304+ di_read_unlock(d, !AuLock_IR);
34305+ if (bopq >= 0 && bopq < err)
34306+ err = bopq;
34307+ }
34308+ }
34309+
34310+out_free:
34311+ dput(parent);
34312+ au_dpages_free(&dpages);
34313+out:
34314+ return err;
34315+}
34316+
1facf9fc 34317+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
34318+{
34319+ for (; bindex >= 0; bindex--)
34320+ if (!au_br_rdonly(au_sbr(sb, bindex)))
34321+ return bindex;
34322+ return -EROFS;
34323+}
34324+
34325+/* top down parent */
392086de
AM
34326+static int au_wbr_create_tdp(struct dentry *dentry,
34327+ unsigned int flags __maybe_unused)
1facf9fc 34328+{
34329+ int err;
5afbbe0d 34330+ aufs_bindex_t btop, bindex;
1facf9fc 34331+ struct super_block *sb;
34332+ struct dentry *parent, *h_parent;
34333+
34334+ sb = dentry->d_sb;
5afbbe0d
AM
34335+ btop = au_dbtop(dentry);
34336+ err = btop;
34337+ if (!au_br_rdonly(au_sbr(sb, btop)))
1facf9fc 34338+ goto out;
34339+
34340+ err = -EROFS;
34341+ parent = dget_parent(dentry);
5afbbe0d 34342+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) {
1facf9fc 34343+ h_parent = au_h_dptr(parent, bindex);
5527c038 34344+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34345+ continue;
34346+
34347+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34348+ err = bindex;
34349+ break;
34350+ }
34351+ }
34352+ dput(parent);
34353+
34354+ /* bottom up here */
4a4d8108 34355+ if (unlikely(err < 0)) {
5afbbe0d 34356+ err = au_wbr_bu(sb, btop - 1);
4a4d8108
AM
34357+ if (err >= 0)
34358+ err = au_wbr_nonopq(dentry, err);
34359+ }
1facf9fc 34360+
4f0767ce 34361+out:
1facf9fc 34362+ AuDbg("b%d\n", err);
34363+ return err;
34364+}
34365+
34366+/* ---------------------------------------------------------------------- */
34367+
34368+/* an exception for the policy other than tdp */
34369+static int au_wbr_create_exp(struct dentry *dentry)
34370+{
34371+ int err;
34372+ aufs_bindex_t bwh, bdiropq;
34373+ struct dentry *parent;
34374+
34375+ err = -1;
34376+ bwh = au_dbwh(dentry);
34377+ parent = dget_parent(dentry);
34378+ bdiropq = au_dbdiropq(parent);
34379+ if (bwh >= 0) {
34380+ if (bdiropq >= 0)
34381+ err = min(bdiropq, bwh);
34382+ else
34383+ err = bwh;
34384+ AuDbg("%d\n", err);
34385+ } else if (bdiropq >= 0) {
34386+ err = bdiropq;
34387+ AuDbg("%d\n", err);
34388+ }
34389+ dput(parent);
34390+
4a4d8108
AM
34391+ if (err >= 0)
34392+ err = au_wbr_nonopq(dentry, err);
34393+
1facf9fc 34394+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
34395+ err = -1;
34396+
34397+ AuDbg("%d\n", err);
34398+ return err;
34399+}
34400+
34401+/* ---------------------------------------------------------------------- */
34402+
34403+/* round robin */
34404+static int au_wbr_create_init_rr(struct super_block *sb)
34405+{
34406+ int err;
34407+
5afbbe0d 34408+ err = au_wbr_bu(sb, au_sbbot(sb));
1facf9fc 34409+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 34410+ /* smp_mb(); */
1facf9fc 34411+
34412+ AuDbg("b%d\n", err);
34413+ return err;
34414+}
34415+
392086de 34416+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags)
1facf9fc 34417+{
34418+ int err, nbr;
34419+ unsigned int u;
5afbbe0d 34420+ aufs_bindex_t bindex, bbot;
1facf9fc 34421+ struct super_block *sb;
34422+ atomic_t *next;
34423+
34424+ err = au_wbr_create_exp(dentry);
34425+ if (err >= 0)
34426+ goto out;
34427+
34428+ sb = dentry->d_sb;
34429+ next = &au_sbi(sb)->si_wbr_rr_next;
5afbbe0d
AM
34430+ bbot = au_sbbot(sb);
34431+ nbr = bbot + 1;
34432+ for (bindex = 0; bindex <= bbot; bindex++) {
392086de 34433+ if (!au_ftest_wbr(flags, DIR)) {
1facf9fc 34434+ err = atomic_dec_return(next) + 1;
34435+ /* modulo for 0 is meaningless */
34436+ if (unlikely(!err))
34437+ err = atomic_dec_return(next) + 1;
34438+ } else
34439+ err = atomic_read(next);
34440+ AuDbg("%d\n", err);
34441+ u = err;
34442+ err = u % nbr;
34443+ AuDbg("%d\n", err);
34444+ if (!au_br_rdonly(au_sbr(sb, err)))
34445+ break;
34446+ err = -EROFS;
34447+ }
34448+
4a4d8108
AM
34449+ if (err >= 0)
34450+ err = au_wbr_nonopq(dentry, err);
34451+
4f0767ce 34452+out:
1facf9fc 34453+ AuDbg("%d\n", err);
34454+ return err;
34455+}
34456+
34457+/* ---------------------------------------------------------------------- */
34458+
34459+/* most free space */
392086de 34460+static void au_mfs(struct dentry *dentry, struct dentry *parent)
1facf9fc 34461+{
34462+ struct super_block *sb;
34463+ struct au_branch *br;
34464+ struct au_wbr_mfs *mfs;
392086de 34465+ struct dentry *h_parent;
5afbbe0d 34466+ aufs_bindex_t bindex, bbot;
1facf9fc 34467+ int err;
34468+ unsigned long long b, bavail;
7f207e10 34469+ struct path h_path;
1facf9fc 34470+ /* reduce the stack usage */
34471+ struct kstatfs *st;
34472+
34473+ st = kmalloc(sizeof(*st), GFP_NOFS);
34474+ if (unlikely(!st)) {
34475+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
34476+ return;
34477+ }
34478+
34479+ bavail = 0;
34480+ sb = dentry->d_sb;
34481+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 34482+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 34483+ mfs->mfs_bindex = -EROFS;
34484+ mfs->mfsrr_bytes = 0;
392086de
AM
34485+ if (!parent) {
34486+ bindex = 0;
5afbbe0d 34487+ bbot = au_sbbot(sb);
392086de 34488+ } else {
5afbbe0d
AM
34489+ bindex = au_dbtop(parent);
34490+ bbot = au_dbtaildir(parent);
392086de
AM
34491+ }
34492+
5afbbe0d 34493+ for (; bindex <= bbot; bindex++) {
392086de
AM
34494+ if (parent) {
34495+ h_parent = au_h_dptr(parent, bindex);
5527c038 34496+ if (!h_parent || d_is_negative(h_parent))
392086de
AM
34497+ continue;
34498+ }
1facf9fc 34499+ br = au_sbr(sb, bindex);
34500+ if (au_br_rdonly(br))
34501+ continue;
34502+
34503+ /* sb->s_root for NFS is unreliable */
86dc4139 34504+ h_path.mnt = au_br_mnt(br);
7f207e10
AM
34505+ h_path.dentry = h_path.mnt->mnt_root;
34506+ err = vfs_statfs(&h_path, st);
1facf9fc 34507+ if (unlikely(err)) {
34508+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
34509+ continue;
34510+ }
34511+
34512+ /* when the available size is equal, select the lower one */
34513+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
34514+ || sizeof(b) < sizeof(st->f_bsize));
34515+ b = st->f_bavail * st->f_bsize;
34516+ br->br_wbr->wbr_bytes = b;
34517+ if (b >= bavail) {
34518+ bavail = b;
34519+ mfs->mfs_bindex = bindex;
34520+ mfs->mfs_jiffy = jiffies;
34521+ }
34522+ }
34523+
34524+ mfs->mfsrr_bytes = bavail;
34525+ AuDbg("b%d\n", mfs->mfs_bindex);
9f237c51 34526+ au_kfree_rcu(st);
1facf9fc 34527+}
34528+
392086de 34529+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34530+{
34531+ int err;
392086de 34532+ struct dentry *parent;
1facf9fc 34533+ struct super_block *sb;
34534+ struct au_wbr_mfs *mfs;
34535+
34536+ err = au_wbr_create_exp(dentry);
34537+ if (err >= 0)
34538+ goto out;
34539+
34540+ sb = dentry->d_sb;
392086de
AM
34541+ parent = NULL;
34542+ if (au_ftest_wbr(flags, PARENT))
34543+ parent = dget_parent(dentry);
1facf9fc 34544+ mfs = &au_sbi(sb)->si_wbr_mfs;
34545+ mutex_lock(&mfs->mfs_lock);
34546+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34547+ || mfs->mfs_bindex < 0
34548+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
392086de 34549+ au_mfs(dentry, parent);
1facf9fc 34550+ mutex_unlock(&mfs->mfs_lock);
34551+ err = mfs->mfs_bindex;
392086de 34552+ dput(parent);
1facf9fc 34553+
4a4d8108
AM
34554+ if (err >= 0)
34555+ err = au_wbr_nonopq(dentry, err);
34556+
4f0767ce 34557+out:
1facf9fc 34558+ AuDbg("b%d\n", err);
34559+ return err;
34560+}
34561+
34562+static int au_wbr_create_init_mfs(struct super_block *sb)
34563+{
34564+ struct au_wbr_mfs *mfs;
34565+
34566+ mfs = &au_sbi(sb)->si_wbr_mfs;
34567+ mutex_init(&mfs->mfs_lock);
34568+ mfs->mfs_jiffy = 0;
34569+ mfs->mfs_bindex = -EROFS;
34570+
34571+ return 0;
34572+}
34573+
34574+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
34575+{
34576+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
34577+ return 0;
34578+}
34579+
34580+/* ---------------------------------------------------------------------- */
34581+
f2c43d5f
AM
34582+/* top down regardless parent, and then mfs */
34583+static int au_wbr_create_tdmfs(struct dentry *dentry,
34584+ unsigned int flags __maybe_unused)
34585+{
34586+ int err;
34587+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs;
34588+ unsigned long long watermark;
34589+ struct super_block *sb;
34590+ struct au_wbr_mfs *mfs;
34591+ struct au_branch *br;
34592+ struct dentry *parent;
34593+
34594+ sb = dentry->d_sb;
34595+ mfs = &au_sbi(sb)->si_wbr_mfs;
34596+ mutex_lock(&mfs->mfs_lock);
34597+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34598+ || mfs->mfs_bindex < 0)
34599+ au_mfs(dentry, /*parent*/NULL);
34600+ watermark = mfs->mfsrr_watermark;
34601+ bmfs = mfs->mfs_bindex;
34602+ mutex_unlock(&mfs->mfs_lock);
34603+
34604+ /* another style of au_wbr_create_exp() */
34605+ bwh = au_dbwh(dentry);
34606+ parent = dget_parent(dentry);
34607+ btail = au_dbtaildir(parent);
34608+ if (bwh >= 0 && bwh < btail)
34609+ btail = bwh;
34610+
34611+ err = au_wbr_nonopq(dentry, btail);
34612+ if (unlikely(err < 0))
34613+ goto out;
34614+ btail = err;
34615+ bfound = -1;
34616+ for (bindex = 0; bindex <= btail; bindex++) {
34617+ br = au_sbr(sb, bindex);
34618+ if (au_br_rdonly(br))
34619+ continue;
34620+ if (br->br_wbr->wbr_bytes > watermark) {
34621+ bfound = bindex;
34622+ break;
34623+ }
34624+ }
34625+ err = bfound;
34626+ if (err < 0)
34627+ err = bmfs;
34628+
34629+out:
34630+ dput(parent);
34631+ AuDbg("b%d\n", err);
34632+ return err;
34633+}
34634+
34635+/* ---------------------------------------------------------------------- */
34636+
1facf9fc 34637+/* most free space and then round robin */
392086de 34638+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags)
1facf9fc 34639+{
34640+ int err;
34641+ struct au_wbr_mfs *mfs;
34642+
392086de 34643+ err = au_wbr_create_mfs(dentry, flags);
1facf9fc 34644+ if (err >= 0) {
34645+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 34646+ mutex_lock(&mfs->mfs_lock);
1facf9fc 34647+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
392086de 34648+ err = au_wbr_create_rr(dentry, flags);
dece6358 34649+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 34650+ }
34651+
34652+ AuDbg("b%d\n", err);
34653+ return err;
34654+}
34655+
34656+static int au_wbr_create_init_mfsrr(struct super_block *sb)
34657+{
34658+ int err;
34659+
34660+ au_wbr_create_init_mfs(sb); /* ignore */
34661+ err = au_wbr_create_init_rr(sb);
34662+
34663+ return err;
34664+}
34665+
34666+/* ---------------------------------------------------------------------- */
34667+
34668+/* top down parent and most free space */
392086de 34669+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34670+{
34671+ int err, e2;
34672+ unsigned long long b;
5afbbe0d 34673+ aufs_bindex_t bindex, btop, bbot;
1facf9fc 34674+ struct super_block *sb;
34675+ struct dentry *parent, *h_parent;
34676+ struct au_branch *br;
34677+
392086de 34678+ err = au_wbr_create_tdp(dentry, flags);
1facf9fc 34679+ if (unlikely(err < 0))
34680+ goto out;
34681+ parent = dget_parent(dentry);
5afbbe0d
AM
34682+ btop = au_dbtop(parent);
34683+ bbot = au_dbtaildir(parent);
34684+ if (btop == bbot)
1facf9fc 34685+ goto out_parent; /* success */
34686+
392086de 34687+ e2 = au_wbr_create_mfs(dentry, flags);
1facf9fc 34688+ if (e2 < 0)
34689+ goto out_parent; /* success */
34690+
34691+ /* when the available size is equal, select upper one */
34692+ sb = dentry->d_sb;
34693+ br = au_sbr(sb, err);
34694+ b = br->br_wbr->wbr_bytes;
34695+ AuDbg("b%d, %llu\n", err, b);
34696+
5afbbe0d 34697+ for (bindex = btop; bindex <= bbot; bindex++) {
1facf9fc 34698+ h_parent = au_h_dptr(parent, bindex);
5527c038 34699+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34700+ continue;
34701+
34702+ br = au_sbr(sb, bindex);
34703+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
34704+ b = br->br_wbr->wbr_bytes;
34705+ err = bindex;
34706+ AuDbg("b%d, %llu\n", err, b);
34707+ }
34708+ }
34709+
4a4d8108
AM
34710+ if (err >= 0)
34711+ err = au_wbr_nonopq(dentry, err);
34712+
4f0767ce 34713+out_parent:
1facf9fc 34714+ dput(parent);
4f0767ce 34715+out:
1facf9fc 34716+ AuDbg("b%d\n", err);
34717+ return err;
34718+}
34719+
34720+/* ---------------------------------------------------------------------- */
34721+
392086de
AM
34722+/*
34723+ * - top down parent
34724+ * - most free space with parent
34725+ * - most free space round-robin regardless parent
34726+ */
34727+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags)
34728+{
34729+ int err;
34730+ unsigned long long watermark;
34731+ struct super_block *sb;
34732+ struct au_branch *br;
34733+ struct au_wbr_mfs *mfs;
34734+
34735+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT);
34736+ if (unlikely(err < 0))
34737+ goto out;
34738+
34739+ sb = dentry->d_sb;
34740+ br = au_sbr(sb, err);
34741+ mfs = &au_sbi(sb)->si_wbr_mfs;
34742+ mutex_lock(&mfs->mfs_lock);
34743+ watermark = mfs->mfsrr_watermark;
34744+ mutex_unlock(&mfs->mfs_lock);
34745+ if (br->br_wbr->wbr_bytes < watermark)
34746+ /* regardless the parent dir */
34747+ err = au_wbr_create_mfsrr(dentry, flags);
34748+
34749+out:
34750+ AuDbg("b%d\n", err);
34751+ return err;
34752+}
34753+
34754+/* ---------------------------------------------------------------------- */
34755+
1facf9fc 34756+/* policies for copyup */
34757+
34758+/* top down parent */
34759+static int au_wbr_copyup_tdp(struct dentry *dentry)
34760+{
392086de 34761+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0);
1facf9fc 34762+}
34763+
34764+/* bottom up parent */
34765+static int au_wbr_copyup_bup(struct dentry *dentry)
34766+{
34767+ int err;
5afbbe0d 34768+ aufs_bindex_t bindex, btop;
1facf9fc 34769+ struct dentry *parent, *h_parent;
34770+ struct super_block *sb;
34771+
34772+ err = -EROFS;
34773+ sb = dentry->d_sb;
34774+ parent = dget_parent(dentry);
5afbbe0d
AM
34775+ btop = au_dbtop(parent);
34776+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) {
1facf9fc 34777+ h_parent = au_h_dptr(parent, bindex);
5527c038 34778+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34779+ continue;
34780+
34781+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34782+ err = bindex;
34783+ break;
34784+ }
34785+ }
34786+ dput(parent);
34787+
34788+ /* bottom up here */
34789+ if (unlikely(err < 0))
5afbbe0d 34790+ err = au_wbr_bu(sb, btop - 1);
1facf9fc 34791+
34792+ AuDbg("b%d\n", err);
34793+ return err;
34794+}
34795+
34796+/* bottom up */
5afbbe0d 34797+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop)
1facf9fc 34798+{
34799+ int err;
34800+
5afbbe0d 34801+ err = au_wbr_bu(dentry->d_sb, btop);
4a4d8108 34802+ AuDbg("b%d\n", err);
5afbbe0d 34803+ if (err > btop)
4a4d8108 34804+ err = au_wbr_nonopq(dentry, err);
1facf9fc 34805+
34806+ AuDbg("b%d\n", err);
34807+ return err;
34808+}
34809+
076b876e
AM
34810+static int au_wbr_copyup_bu(struct dentry *dentry)
34811+{
34812+ int err;
5afbbe0d 34813+ aufs_bindex_t btop;
076b876e 34814+
5afbbe0d
AM
34815+ btop = au_dbtop(dentry);
34816+ err = au_wbr_do_copyup_bu(dentry, btop);
076b876e
AM
34817+ return err;
34818+}
34819+
1facf9fc 34820+/* ---------------------------------------------------------------------- */
34821+
34822+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
34823+ [AuWbrCopyup_TDP] = {
34824+ .copyup = au_wbr_copyup_tdp
34825+ },
34826+ [AuWbrCopyup_BUP] = {
34827+ .copyup = au_wbr_copyup_bup
34828+ },
34829+ [AuWbrCopyup_BU] = {
34830+ .copyup = au_wbr_copyup_bu
34831+ }
34832+};
34833+
34834+struct au_wbr_create_operations au_wbr_create_ops[] = {
34835+ [AuWbrCreate_TDP] = {
34836+ .create = au_wbr_create_tdp
34837+ },
34838+ [AuWbrCreate_RR] = {
34839+ .create = au_wbr_create_rr,
34840+ .init = au_wbr_create_init_rr
34841+ },
34842+ [AuWbrCreate_MFS] = {
34843+ .create = au_wbr_create_mfs,
34844+ .init = au_wbr_create_init_mfs,
34845+ .fin = au_wbr_create_fin_mfs
34846+ },
34847+ [AuWbrCreate_MFSV] = {
34848+ .create = au_wbr_create_mfs,
34849+ .init = au_wbr_create_init_mfs,
34850+ .fin = au_wbr_create_fin_mfs
34851+ },
34852+ [AuWbrCreate_MFSRR] = {
34853+ .create = au_wbr_create_mfsrr,
34854+ .init = au_wbr_create_init_mfsrr,
34855+ .fin = au_wbr_create_fin_mfs
34856+ },
34857+ [AuWbrCreate_MFSRRV] = {
34858+ .create = au_wbr_create_mfsrr,
34859+ .init = au_wbr_create_init_mfsrr,
34860+ .fin = au_wbr_create_fin_mfs
34861+ },
f2c43d5f
AM
34862+ [AuWbrCreate_TDMFS] = {
34863+ .create = au_wbr_create_tdmfs,
34864+ .init = au_wbr_create_init_mfs,
34865+ .fin = au_wbr_create_fin_mfs
34866+ },
34867+ [AuWbrCreate_TDMFSV] = {
34868+ .create = au_wbr_create_tdmfs,
34869+ .init = au_wbr_create_init_mfs,
34870+ .fin = au_wbr_create_fin_mfs
34871+ },
1facf9fc 34872+ [AuWbrCreate_PMFS] = {
34873+ .create = au_wbr_create_pmfs,
34874+ .init = au_wbr_create_init_mfs,
34875+ .fin = au_wbr_create_fin_mfs
34876+ },
34877+ [AuWbrCreate_PMFSV] = {
34878+ .create = au_wbr_create_pmfs,
34879+ .init = au_wbr_create_init_mfs,
34880+ .fin = au_wbr_create_fin_mfs
392086de
AM
34881+ },
34882+ [AuWbrCreate_PMFSRR] = {
34883+ .create = au_wbr_create_pmfsrr,
34884+ .init = au_wbr_create_init_mfsrr,
34885+ .fin = au_wbr_create_fin_mfs
34886+ },
34887+ [AuWbrCreate_PMFSRRV] = {
34888+ .create = au_wbr_create_pmfsrr,
34889+ .init = au_wbr_create_init_mfsrr,
34890+ .fin = au_wbr_create_fin_mfs
1facf9fc 34891+ }
34892+};
7f207e10 34893diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
fbc438ed
JR
34894--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 08:00:00.000000000 +0800
34895+++ linux/fs/aufs/whout.c 2019-07-11 21:21:54.382384486 +0800
062440b3 34896@@ -0,0 +1,1062 @@
cd7a4cd9 34897+// SPDX-License-Identifier: GPL-2.0
1facf9fc 34898+/*
ba1aed25 34899+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 34900+ *
34901+ * This program, aufs is free software; you can redistribute it and/or modify
34902+ * it under the terms of the GNU General Public License as published by
34903+ * the Free Software Foundation; either version 2 of the License, or
34904+ * (at your option) any later version.
dece6358
AM
34905+ *
34906+ * This program is distributed in the hope that it will be useful,
34907+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34908+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34909+ * GNU General Public License for more details.
34910+ *
34911+ * You should have received a copy of the GNU General Public License
523b37e3 34912+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34913+ */
34914+
34915+/*
34916+ * whiteout for logical deletion and opaque directory
34917+ */
34918+
1facf9fc 34919+#include "aufs.h"
34920+
cd7a4cd9 34921+#define WH_MASK 0444
1facf9fc 34922+
34923+/*
34924+ * If a directory contains this file, then it is opaque. We start with the
34925+ * .wh. flag so that it is blocked by lookup.
34926+ */
0c3ec466
AM
34927+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
34928+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 34929+
34930+/*
34931+ * generate whiteout name, which is NOT terminated by NULL.
34932+ * @name: original d_name.name
34933+ * @len: original d_name.len
34934+ * @wh: whiteout qstr
34935+ * returns zero when succeeds, otherwise error.
34936+ * succeeded value as wh->name should be freed by kfree().
34937+ */
34938+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
34939+{
34940+ char *p;
34941+
34942+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
34943+ return -ENAMETOOLONG;
34944+
34945+ wh->len = name->len + AUFS_WH_PFX_LEN;
34946+ p = kmalloc(wh->len, GFP_NOFS);
34947+ wh->name = p;
34948+ if (p) {
34949+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
34950+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
34951+ /* smp_mb(); */
34952+ return 0;
34953+ }
34954+ return -ENOMEM;
34955+}
34956+
34957+/* ---------------------------------------------------------------------- */
34958+
34959+/*
34960+ * test if the @wh_name exists under @h_parent.
34961+ * @try_sio specifies the necessary of super-io.
34962+ */
076b876e 34963+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio)
1facf9fc 34964+{
34965+ int err;
34966+ struct dentry *wh_dentry;
1facf9fc 34967+
1facf9fc 34968+ if (!try_sio)
b4510431 34969+ wh_dentry = vfsub_lkup_one(wh_name, h_parent);
1facf9fc 34970+ else
076b876e 34971+ wh_dentry = au_sio_lkup_one(wh_name, h_parent);
1facf9fc 34972+ err = PTR_ERR(wh_dentry);
2000de60
JR
34973+ if (IS_ERR(wh_dentry)) {
34974+ if (err == -ENAMETOOLONG)
34975+ err = 0;
1facf9fc 34976+ goto out;
2000de60 34977+ }
1facf9fc 34978+
34979+ err = 0;
5527c038 34980+ if (d_is_negative(wh_dentry))
1facf9fc 34981+ goto out_wh; /* success */
34982+
34983+ err = 1;
7e9cd9fe 34984+ if (d_is_reg(wh_dentry))
1facf9fc 34985+ goto out_wh; /* success */
34986+
34987+ err = -EIO;
523b37e3 34988+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n",
5527c038 34989+ wh_dentry, d_inode(wh_dentry)->i_mode);
1facf9fc 34990+
4f0767ce 34991+out_wh:
1facf9fc 34992+ dput(wh_dentry);
4f0767ce 34993+out:
1facf9fc 34994+ return err;
34995+}
34996+
34997+/*
34998+ * test if the @h_dentry sets opaque or not.
34999+ */
076b876e 35000+int au_diropq_test(struct dentry *h_dentry)
1facf9fc 35001+{
35002+ int err;
35003+ struct inode *h_dir;
35004+
5527c038 35005+ h_dir = d_inode(h_dentry);
076b876e 35006+ err = au_wh_test(h_dentry, &diropq_name,
1facf9fc 35007+ au_test_h_perm_sio(h_dir, MAY_EXEC));
35008+ return err;
35009+}
35010+
35011+/*
35012+ * returns a negative dentry whose name is unique and temporary.
35013+ */
35014+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
35015+ struct qstr *prefix)
35016+{
1facf9fc 35017+ struct dentry *dentry;
35018+ int i;
027c5e7a 35019+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 35020+ *name, *p;
027c5e7a 35021+ /* strict atomic_t is unnecessary here */
1facf9fc 35022+ static unsigned short cnt;
35023+ struct qstr qs;
35024+
4a4d8108
AM
35025+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
35026+
1facf9fc 35027+ name = defname;
027c5e7a
AM
35028+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
35029+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 35030+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 35031+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 35032+ goto out;
35033+ dentry = ERR_PTR(-ENOMEM);
35034+ name = kmalloc(qs.len + 1, GFP_NOFS);
35035+ if (unlikely(!name))
35036+ goto out;
35037+ }
35038+
35039+ /* doubly whiteout-ed */
35040+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
35041+ p = name + AUFS_WH_PFX_LEN * 2;
35042+ memcpy(p, prefix->name, prefix->len);
35043+ p += prefix->len;
35044+ *p++ = '.';
4a4d8108 35045+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 35046+
35047+ qs.name = name;
35048+ for (i = 0; i < 3; i++) {
b752ccd1 35049+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
076b876e 35050+ dentry = au_sio_lkup_one(&qs, h_parent);
5527c038 35051+ if (IS_ERR(dentry) || d_is_negative(dentry))
1facf9fc 35052+ goto out_name;
35053+ dput(dentry);
35054+ }
0c3ec466 35055+ /* pr_warn("could not get random name\n"); */
1facf9fc 35056+ dentry = ERR_PTR(-EEXIST);
35057+ AuDbg("%.*s\n", AuLNPair(&qs));
35058+ BUG();
35059+
4f0767ce 35060+out_name:
1facf9fc 35061+ if (name != defname)
9f237c51 35062+ au_kfree_try_rcu(name);
4f0767ce 35063+out:
4a4d8108 35064+ AuTraceErrPtr(dentry);
1facf9fc 35065+ return dentry;
1facf9fc 35066+}
35067+
35068+/*
35069+ * rename the @h_dentry on @br to the whiteouted temporary name.
35070+ */
35071+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
35072+{
35073+ int err;
35074+ struct path h_path = {
86dc4139 35075+ .mnt = au_br_mnt(br)
1facf9fc 35076+ };
523b37e3 35077+ struct inode *h_dir, *delegated;
1facf9fc 35078+ struct dentry *h_parent;
35079+
35080+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 35081+ h_dir = d_inode(h_parent);
1facf9fc 35082+ IMustLock(h_dir);
35083+
35084+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
35085+ err = PTR_ERR(h_path.dentry);
35086+ if (IS_ERR(h_path.dentry))
35087+ goto out;
35088+
35089+ /* under the same dir, no need to lock_rename() */
523b37e3 35090+ delegated = NULL;
f2c43d5f
AM
35091+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated,
35092+ /*flags*/0);
1facf9fc 35093+ AuTraceErr(err);
523b37e3
AM
35094+ if (unlikely(err == -EWOULDBLOCK)) {
35095+ pr_warn("cannot retry for NFSv4 delegation"
35096+ " for an internal rename\n");
35097+ iput(delegated);
35098+ }
1facf9fc 35099+ dput(h_path.dentry);
35100+
4f0767ce 35101+out:
4a4d8108 35102+ AuTraceErr(err);
1facf9fc 35103+ return err;
35104+}
35105+
35106+/* ---------------------------------------------------------------------- */
35107+/*
35108+ * functions for removing a whiteout
35109+ */
35110+
35111+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
35112+{
523b37e3
AM
35113+ int err, force;
35114+ struct inode *delegated;
1facf9fc 35115+
35116+ /*
35117+ * forces superio when the dir has a sticky bit.
35118+ * this may be a violation of unix fs semantics.
35119+ */
35120+ force = (h_dir->i_mode & S_ISVTX)
5527c038 35121+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid);
523b37e3
AM
35122+ delegated = NULL;
35123+ err = vfsub_unlink(h_dir, h_path, &delegated, force);
35124+ if (unlikely(err == -EWOULDBLOCK)) {
35125+ pr_warn("cannot retry for NFSv4 delegation"
35126+ " for an internal unlink\n");
35127+ iput(delegated);
35128+ }
35129+ return err;
1facf9fc 35130+}
35131+
35132+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
35133+ struct dentry *dentry)
35134+{
35135+ int err;
35136+
35137+ err = do_unlink_wh(h_dir, h_path);
35138+ if (!err && dentry)
35139+ au_set_dbwh(dentry, -1);
35140+
35141+ return err;
35142+}
35143+
35144+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
35145+ struct au_branch *br)
35146+{
35147+ int err;
35148+ struct path h_path = {
86dc4139 35149+ .mnt = au_br_mnt(br)
1facf9fc 35150+ };
35151+
35152+ err = 0;
b4510431 35153+ h_path.dentry = vfsub_lkup_one(wh, h_parent);
1facf9fc 35154+ if (IS_ERR(h_path.dentry))
35155+ err = PTR_ERR(h_path.dentry);
35156+ else {
5527c038
JR
35157+ if (d_is_reg(h_path.dentry))
35158+ err = do_unlink_wh(d_inode(h_parent), &h_path);
1facf9fc 35159+ dput(h_path.dentry);
35160+ }
35161+
35162+ return err;
35163+}
35164+
35165+/* ---------------------------------------------------------------------- */
35166+/*
35167+ * initialize/clean whiteout for a branch
35168+ */
35169+
35170+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
35171+ const int isdir)
35172+{
35173+ int err;
523b37e3 35174+ struct inode *delegated;
1facf9fc 35175+
5527c038 35176+ if (d_is_negative(whpath->dentry))
1facf9fc 35177+ return;
35178+
86dc4139
AM
35179+ if (isdir)
35180+ err = vfsub_rmdir(h_dir, whpath);
523b37e3
AM
35181+ else {
35182+ delegated = NULL;
35183+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0);
35184+ if (unlikely(err == -EWOULDBLOCK)) {
35185+ pr_warn("cannot retry for NFSv4 delegation"
35186+ " for an internal unlink\n");
35187+ iput(delegated);
35188+ }
35189+ }
1facf9fc 35190+ if (unlikely(err))
523b37e3
AM
35191+ pr_warn("failed removing %pd (%d), ignored.\n",
35192+ whpath->dentry, err);
1facf9fc 35193+}
35194+
35195+static int test_linkable(struct dentry *h_root)
35196+{
5527c038 35197+ struct inode *h_dir = d_inode(h_root);
1facf9fc 35198+
35199+ if (h_dir->i_op->link)
35200+ return 0;
35201+
523b37e3
AM
35202+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n",
35203+ h_root, au_sbtype(h_root->d_sb));
1facf9fc 35204+ return -ENOSYS;
35205+}
35206+
35207+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
35208+static int au_whdir(struct inode *h_dir, struct path *path)
35209+{
35210+ int err;
35211+
35212+ err = -EEXIST;
5527c038 35213+ if (d_is_negative(path->dentry)) {
cd7a4cd9 35214+ int mode = 0700;
1facf9fc 35215+
35216+ if (au_test_nfs(path->dentry->d_sb))
cd7a4cd9 35217+ mode |= 0111;
86dc4139 35218+ err = vfsub_mkdir(h_dir, path, mode);
2000de60 35219+ } else if (d_is_dir(path->dentry))
1facf9fc 35220+ err = 0;
35221+ else
523b37e3 35222+ pr_err("unknown %pd exists\n", path->dentry);
1facf9fc 35223+
35224+ return err;
35225+}
35226+
35227+struct au_wh_base {
35228+ const struct qstr *name;
35229+ struct dentry *dentry;
35230+};
35231+
35232+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
35233+ struct path *h_path)
35234+{
35235+ h_path->dentry = base[AuBrWh_BASE].dentry;
35236+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35237+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35238+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35239+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35240+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35241+}
35242+
35243+/*
35244+ * returns tri-state,
c1595e42 35245+ * minus: error, caller should print the message
acd2b654 35246+ * zero: success
c1595e42 35247+ * plus: error, caller should NOT print the message
1facf9fc 35248+ */
35249+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
35250+ int do_plink, struct au_wh_base base[],
35251+ struct path *h_path)
35252+{
35253+ int err;
35254+ struct inode *h_dir;
35255+
5527c038 35256+ h_dir = d_inode(h_root);
1facf9fc 35257+ h_path->dentry = base[AuBrWh_BASE].dentry;
35258+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35259+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35260+ if (do_plink) {
35261+ err = test_linkable(h_root);
35262+ if (unlikely(err)) {
35263+ err = 1;
35264+ goto out;
35265+ }
35266+
35267+ err = au_whdir(h_dir, h_path);
35268+ if (unlikely(err))
35269+ goto out;
35270+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35271+ } else
35272+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35273+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35274+ err = au_whdir(h_dir, h_path);
35275+ if (unlikely(err))
35276+ goto out;
35277+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35278+
4f0767ce 35279+out:
1facf9fc 35280+ return err;
35281+}
35282+
35283+/*
35284+ * for the moment, aufs supports the branch filesystem which does not support
35285+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
35286+ * copyup failed. finally, such filesystem will not be used as the writable
35287+ * branch.
35288+ *
35289+ * returns tri-state, see above.
35290+ */
35291+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
35292+ int do_plink, struct au_wh_base base[],
35293+ struct path *h_path)
35294+{
35295+ int err;
35296+ struct inode *h_dir;
35297+
1308ab2a 35298+ WbrWhMustWriteLock(wbr);
35299+
1facf9fc 35300+ err = test_linkable(h_root);
35301+ if (unlikely(err)) {
35302+ err = 1;
35303+ goto out;
35304+ }
35305+
35306+ /*
35307+ * todo: should this create be done in /sbin/mount.aufs helper?
35308+ */
35309+ err = -EEXIST;
5527c038
JR
35310+ h_dir = d_inode(h_root);
35311+ if (d_is_negative(base[AuBrWh_BASE].dentry)) {
86dc4139
AM
35312+ h_path->dentry = base[AuBrWh_BASE].dentry;
35313+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true);
7e9cd9fe 35314+ } else if (d_is_reg(base[AuBrWh_BASE].dentry))
1facf9fc 35315+ err = 0;
35316+ else
523b37e3 35317+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry);
1facf9fc 35318+ if (unlikely(err))
35319+ goto out;
35320+
35321+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35322+ if (do_plink) {
35323+ err = au_whdir(h_dir, h_path);
35324+ if (unlikely(err))
35325+ goto out;
35326+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35327+ } else
35328+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35329+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
35330+
35331+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35332+ err = au_whdir(h_dir, h_path);
35333+ if (unlikely(err))
35334+ goto out;
35335+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35336+
4f0767ce 35337+out:
1facf9fc 35338+ return err;
35339+}
35340+
35341+/*
35342+ * initialize the whiteout base file/dir for @br.
35343+ */
86dc4139 35344+int au_wh_init(struct au_branch *br, struct super_block *sb)
1facf9fc 35345+{
35346+ int err, i;
35347+ const unsigned char do_plink
35348+ = !!au_opt_test(au_mntflags(sb), PLINK);
1facf9fc 35349+ struct inode *h_dir;
86dc4139
AM
35350+ struct path path = br->br_path;
35351+ struct dentry *h_root = path.dentry;
1facf9fc 35352+ struct au_wbr *wbr = br->br_wbr;
35353+ static const struct qstr base_name[] = {
0c3ec466
AM
35354+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
35355+ sizeof(AUFS_BASE_NAME) - 1),
35356+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
35357+ sizeof(AUFS_PLINKDIR_NAME) - 1),
35358+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
35359+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 35360+ };
35361+ struct au_wh_base base[] = {
35362+ [AuBrWh_BASE] = {
35363+ .name = base_name + AuBrWh_BASE,
35364+ .dentry = NULL
35365+ },
35366+ [AuBrWh_PLINK] = {
35367+ .name = base_name + AuBrWh_PLINK,
35368+ .dentry = NULL
35369+ },
35370+ [AuBrWh_ORPH] = {
35371+ .name = base_name + AuBrWh_ORPH,
35372+ .dentry = NULL
35373+ }
35374+ };
35375+
1308ab2a 35376+ if (wbr)
35377+ WbrWhMustWriteLock(wbr);
1facf9fc 35378+
1facf9fc 35379+ for (i = 0; i < AuBrWh_Last; i++) {
35380+ /* doubly whiteouted */
35381+ struct dentry *d;
35382+
35383+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
35384+ err = PTR_ERR(d);
35385+ if (IS_ERR(d))
35386+ goto out;
35387+
35388+ base[i].dentry = d;
35389+ AuDebugOn(wbr
35390+ && wbr->wbr_wh[i]
35391+ && wbr->wbr_wh[i] != base[i].dentry);
35392+ }
35393+
35394+ if (wbr)
35395+ for (i = 0; i < AuBrWh_Last; i++) {
35396+ dput(wbr->wbr_wh[i]);
35397+ wbr->wbr_wh[i] = NULL;
35398+ }
35399+
35400+ err = 0;
1e00d052 35401+ if (!au_br_writable(br->br_perm)) {
5527c038 35402+ h_dir = d_inode(h_root);
1facf9fc 35403+ au_wh_init_ro(h_dir, base, &path);
1e00d052 35404+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 35405+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
35406+ if (err > 0)
35407+ goto out;
35408+ else if (err)
35409+ goto out_err;
1e00d052 35410+ } else {
1facf9fc 35411+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
35412+ if (err > 0)
35413+ goto out;
35414+ else if (err)
35415+ goto out_err;
1facf9fc 35416+ }
35417+ goto out; /* success */
35418+
4f0767ce 35419+out_err:
523b37e3
AM
35420+ pr_err("an error(%d) on the writable branch %pd(%s)\n",
35421+ err, h_root, au_sbtype(h_root->d_sb));
4f0767ce 35422+out:
1facf9fc 35423+ for (i = 0; i < AuBrWh_Last; i++)
35424+ dput(base[i].dentry);
35425+ return err;
35426+}
35427+
35428+/* ---------------------------------------------------------------------- */
35429+/*
35430+ * whiteouts are all hard-linked usually.
35431+ * when its link count reaches a ceiling, we create a new whiteout base
35432+ * asynchronously.
35433+ */
35434+
35435+struct reinit_br_wh {
35436+ struct super_block *sb;
35437+ struct au_branch *br;
35438+};
35439+
35440+static void reinit_br_wh(void *arg)
35441+{
35442+ int err;
35443+ aufs_bindex_t bindex;
35444+ struct path h_path;
35445+ struct reinit_br_wh *a = arg;
35446+ struct au_wbr *wbr;
523b37e3 35447+ struct inode *dir, *delegated;
1facf9fc 35448+ struct dentry *h_root;
35449+ struct au_hinode *hdir;
35450+
35451+ err = 0;
35452+ wbr = a->br->br_wbr;
35453+ /* big aufs lock */
35454+ si_noflush_write_lock(a->sb);
35455+ if (!au_br_writable(a->br->br_perm))
35456+ goto out;
35457+ bindex = au_br_index(a->sb, a->br->br_id);
35458+ if (unlikely(bindex < 0))
35459+ goto out;
35460+
1308ab2a 35461+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
5527c038 35462+ dir = d_inode(a->sb->s_root);
1facf9fc 35463+ hdir = au_hi(dir, bindex);
35464+ h_root = au_h_dptr(a->sb->s_root, bindex);
86dc4139 35465+ AuDebugOn(h_root != au_br_dentry(a->br));
1facf9fc 35466+
5afbbe0d 35467+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 35468+ wbr_wh_write_lock(wbr);
35469+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
35470+ h_root, a->br);
35471+ if (!err) {
86dc4139
AM
35472+ h_path.dentry = wbr->wbr_whbase;
35473+ h_path.mnt = au_br_mnt(a->br);
523b37e3
AM
35474+ delegated = NULL;
35475+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated,
35476+ /*force*/0);
35477+ if (unlikely(err == -EWOULDBLOCK)) {
35478+ pr_warn("cannot retry for NFSv4 delegation"
35479+ " for an internal unlink\n");
35480+ iput(delegated);
35481+ }
1facf9fc 35482+ } else {
523b37e3 35483+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase);
1facf9fc 35484+ err = 0;
35485+ }
35486+ dput(wbr->wbr_whbase);
35487+ wbr->wbr_whbase = NULL;
35488+ if (!err)
86dc4139 35489+ err = au_wh_init(a->br, a->sb);
1facf9fc 35490+ wbr_wh_write_unlock(wbr);
5afbbe0d 35491+ au_hn_inode_unlock(hdir);
1308ab2a 35492+ di_read_unlock(a->sb->s_root, AuLock_IR);
076b876e
AM
35493+ if (!err)
35494+ au_fhsm_wrote(a->sb, bindex, /*force*/0);
1facf9fc 35495+
4f0767ce 35496+out:
1facf9fc 35497+ if (wbr)
35498+ atomic_dec(&wbr->wbr_wh_running);
acd2b654 35499+ au_lcnt_dec(&a->br->br_count);
1facf9fc 35500+ si_write_unlock(a->sb);
027c5e7a 35501+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
9f237c51 35502+ au_kfree_rcu(a);
1facf9fc 35503+ if (unlikely(err))
35504+ AuIOErr("err %d\n", err);
35505+}
35506+
35507+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
35508+{
35509+ int do_dec, wkq_err;
35510+ struct reinit_br_wh *arg;
35511+
35512+ do_dec = 1;
35513+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
35514+ goto out;
35515+
35516+ /* ignore ENOMEM */
35517+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
35518+ if (arg) {
35519+ /*
35520+ * dec(wh_running), kfree(arg) and dec(br_count)
35521+ * in reinit function
35522+ */
35523+ arg->sb = sb;
35524+ arg->br = br;
acd2b654 35525+ au_lcnt_inc(&br->br_count);
53392da6 35526+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 35527+ if (unlikely(wkq_err)) {
35528+ atomic_dec(&br->br_wbr->wbr_wh_running);
acd2b654 35529+ au_lcnt_dec(&br->br_count);
9f237c51 35530+ au_kfree_rcu(arg);
1facf9fc 35531+ }
35532+ do_dec = 0;
35533+ }
35534+
4f0767ce 35535+out:
1facf9fc 35536+ if (do_dec)
35537+ atomic_dec(&br->br_wbr->wbr_wh_running);
35538+}
35539+
35540+/* ---------------------------------------------------------------------- */
35541+
35542+/*
35543+ * create the whiteout @wh.
35544+ */
35545+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
35546+ struct dentry *wh)
35547+{
35548+ int err;
35549+ struct path h_path = {
35550+ .dentry = wh
35551+ };
35552+ struct au_branch *br;
35553+ struct au_wbr *wbr;
35554+ struct dentry *h_parent;
523b37e3 35555+ struct inode *h_dir, *delegated;
1facf9fc 35556+
35557+ h_parent = wh->d_parent; /* dir inode is locked */
5527c038 35558+ h_dir = d_inode(h_parent);
1facf9fc 35559+ IMustLock(h_dir);
35560+
35561+ br = au_sbr(sb, bindex);
86dc4139 35562+ h_path.mnt = au_br_mnt(br);
1facf9fc 35563+ wbr = br->br_wbr;
35564+ wbr_wh_read_lock(wbr);
35565+ if (wbr->wbr_whbase) {
523b37e3
AM
35566+ delegated = NULL;
35567+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated);
35568+ if (unlikely(err == -EWOULDBLOCK)) {
35569+ pr_warn("cannot retry for NFSv4 delegation"
35570+ " for an internal link\n");
35571+ iput(delegated);
35572+ }
1facf9fc 35573+ if (!err || err != -EMLINK)
35574+ goto out;
35575+
35576+ /* link count full. re-initialize br_whbase. */
35577+ kick_reinit_br_wh(sb, br);
35578+ }
35579+
35580+ /* return this error in this context */
b4510431 35581+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true);
076b876e
AM
35582+ if (!err)
35583+ au_fhsm_wrote(sb, bindex, /*force*/0);
1facf9fc 35584+
4f0767ce 35585+out:
1facf9fc 35586+ wbr_wh_read_unlock(wbr);
35587+ return err;
35588+}
35589+
35590+/* ---------------------------------------------------------------------- */
35591+
35592+/*
35593+ * create or remove the diropq.
35594+ */
35595+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
35596+ unsigned int flags)
35597+{
35598+ struct dentry *opq_dentry, *h_dentry;
35599+ struct super_block *sb;
35600+ struct au_branch *br;
35601+ int err;
35602+
35603+ sb = dentry->d_sb;
35604+ br = au_sbr(sb, bindex);
35605+ h_dentry = au_h_dptr(dentry, bindex);
b4510431 35606+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
1facf9fc 35607+ if (IS_ERR(opq_dentry))
35608+ goto out;
35609+
35610+ if (au_ftest_diropq(flags, CREATE)) {
35611+ err = link_or_create_wh(sb, bindex, opq_dentry);
35612+ if (!err) {
35613+ au_set_dbdiropq(dentry, bindex);
35614+ goto out; /* success */
35615+ }
35616+ } else {
35617+ struct path tmp = {
35618+ .dentry = opq_dentry,
86dc4139 35619+ .mnt = au_br_mnt(br)
1facf9fc 35620+ };
5527c038 35621+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp);
1facf9fc 35622+ if (!err)
35623+ au_set_dbdiropq(dentry, -1);
35624+ }
35625+ dput(opq_dentry);
35626+ opq_dentry = ERR_PTR(err);
35627+
4f0767ce 35628+out:
1facf9fc 35629+ return opq_dentry;
35630+}
35631+
35632+struct do_diropq_args {
35633+ struct dentry **errp;
35634+ struct dentry *dentry;
35635+ aufs_bindex_t bindex;
35636+ unsigned int flags;
35637+};
35638+
35639+static void call_do_diropq(void *args)
35640+{
35641+ struct do_diropq_args *a = args;
35642+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
35643+}
35644+
35645+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
35646+ unsigned int flags)
35647+{
35648+ struct dentry *diropq, *h_dentry;
35649+
35650+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 35651+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE))
1facf9fc 35652+ diropq = do_diropq(dentry, bindex, flags);
35653+ else {
35654+ int wkq_err;
35655+ struct do_diropq_args args = {
35656+ .errp = &diropq,
35657+ .dentry = dentry,
35658+ .bindex = bindex,
35659+ .flags = flags
35660+ };
35661+
35662+ wkq_err = au_wkq_wait(call_do_diropq, &args);
35663+ if (unlikely(wkq_err))
35664+ diropq = ERR_PTR(wkq_err);
35665+ }
35666+
35667+ return diropq;
35668+}
35669+
35670+/* ---------------------------------------------------------------------- */
35671+
35672+/*
35673+ * lookup whiteout dentry.
35674+ * @h_parent: lower parent dentry which must exist and be locked
35675+ * @base_name: name of dentry which will be whiteouted
35676+ * returns dentry for whiteout.
35677+ */
35678+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
35679+ struct au_branch *br)
35680+{
35681+ int err;
35682+ struct qstr wh_name;
35683+ struct dentry *wh_dentry;
35684+
35685+ err = au_wh_name_alloc(&wh_name, base_name);
35686+ wh_dentry = ERR_PTR(err);
35687+ if (!err) {
b4510431 35688+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
9f237c51 35689+ au_kfree_try_rcu(wh_name.name);
1facf9fc 35690+ }
35691+ return wh_dentry;
35692+}
35693+
35694+/*
35695+ * link/create a whiteout for @dentry on @bindex.
35696+ */
35697+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
35698+ struct dentry *h_parent)
35699+{
35700+ struct dentry *wh_dentry;
35701+ struct super_block *sb;
35702+ int err;
35703+
35704+ sb = dentry->d_sb;
35705+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
5527c038 35706+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) {
1facf9fc 35707+ err = link_or_create_wh(sb, bindex, wh_dentry);
076b876e 35708+ if (!err) {
1facf9fc 35709+ au_set_dbwh(dentry, bindex);
076b876e
AM
35710+ au_fhsm_wrote(sb, bindex, /*force*/0);
35711+ } else {
1facf9fc 35712+ dput(wh_dentry);
35713+ wh_dentry = ERR_PTR(err);
35714+ }
35715+ }
35716+
35717+ return wh_dentry;
35718+}
35719+
35720+/* ---------------------------------------------------------------------- */
35721+
35722+/* Delete all whiteouts in this directory on branch bindex. */
35723+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
35724+ aufs_bindex_t bindex, struct au_branch *br)
35725+{
35726+ int err;
35727+ unsigned long ul, n;
35728+ struct qstr wh_name;
35729+ char *p;
35730+ struct hlist_head *head;
c06a8ce3 35731+ struct au_vdir_wh *pos;
1facf9fc 35732+ struct au_vdir_destr *str;
35733+
35734+ err = -ENOMEM;
537831f9 35735+ p = (void *)__get_free_page(GFP_NOFS);
1facf9fc 35736+ wh_name.name = p;
35737+ if (unlikely(!wh_name.name))
35738+ goto out;
35739+
35740+ err = 0;
35741+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
35742+ p += AUFS_WH_PFX_LEN;
35743+ n = whlist->nh_num;
35744+ head = whlist->nh_head;
35745+ for (ul = 0; !err && ul < n; ul++, head++) {
c06a8ce3
AM
35746+ hlist_for_each_entry(pos, head, wh_hash) {
35747+ if (pos->wh_bindex != bindex)
1facf9fc 35748+ continue;
35749+
c06a8ce3 35750+ str = &pos->wh_str;
1facf9fc 35751+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
35752+ memcpy(p, str->name, str->len);
35753+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
35754+ err = unlink_wh_name(h_dentry, &wh_name, br);
35755+ if (!err)
35756+ continue;
35757+ break;
35758+ }
35759+ AuIOErr("whiteout name too long %.*s\n",
35760+ str->len, str->name);
35761+ err = -EIO;
35762+ break;
35763+ }
35764+ }
1c60b727 35765+ free_page((unsigned long)wh_name.name);
1facf9fc 35766+
4f0767ce 35767+out:
1facf9fc 35768+ return err;
35769+}
35770+
35771+struct del_wh_children_args {
35772+ int *errp;
35773+ struct dentry *h_dentry;
1308ab2a 35774+ struct au_nhash *whlist;
1facf9fc 35775+ aufs_bindex_t bindex;
35776+ struct au_branch *br;
35777+};
35778+
35779+static void call_del_wh_children(void *args)
35780+{
35781+ struct del_wh_children_args *a = args;
1308ab2a 35782+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 35783+}
35784+
35785+/* ---------------------------------------------------------------------- */
35786+
35787+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
35788+{
35789+ struct au_whtmp_rmdir *whtmp;
dece6358 35790+ int err;
1308ab2a 35791+ unsigned int rdhash;
dece6358
AM
35792+
35793+ SiMustAnyLock(sb);
1facf9fc 35794+
be52b249 35795+ whtmp = kzalloc(sizeof(*whtmp), gfp);
dece6358
AM
35796+ if (unlikely(!whtmp)) {
35797+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 35798+ goto out;
dece6358 35799+ }
1facf9fc 35800+
1308ab2a 35801+ /* no estimation for dir size */
35802+ rdhash = au_sbi(sb)->si_rdhash;
35803+ if (!rdhash)
35804+ rdhash = AUFS_RDHASH_DEF;
35805+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
35806+ if (unlikely(err)) {
9f237c51 35807+ au_kfree_rcu(whtmp);
1308ab2a 35808+ whtmp = ERR_PTR(err);
35809+ }
dece6358 35810+
4f0767ce 35811+out:
dece6358 35812+ return whtmp;
1facf9fc 35813+}
35814+
35815+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
35816+{
027c5e7a 35817+ if (whtmp->br)
acd2b654 35818+ au_lcnt_dec(&whtmp->br->br_count);
1facf9fc 35819+ dput(whtmp->wh_dentry);
35820+ iput(whtmp->dir);
dece6358 35821+ au_nhash_wh_free(&whtmp->whlist);
9f237c51 35822+ au_kfree_rcu(whtmp);
1facf9fc 35823+}
35824+
35825+/*
35826+ * rmdir the whiteouted temporary named dir @h_dentry.
35827+ * @whlist: whiteouted children.
35828+ */
35829+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
35830+ struct dentry *wh_dentry, struct au_nhash *whlist)
35831+{
35832+ int err;
2000de60 35833+ unsigned int h_nlink;
1facf9fc 35834+ struct path h_tmp;
35835+ struct inode *wh_inode, *h_dir;
35836+ struct au_branch *br;
35837+
5527c038 35838+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
1facf9fc 35839+ IMustLock(h_dir);
35840+
35841+ br = au_sbr(dir->i_sb, bindex);
5527c038 35842+ wh_inode = d_inode(wh_dentry);
febd17d6 35843+ inode_lock_nested(wh_inode, AuLsc_I_CHILD);
1facf9fc 35844+
35845+ /*
35846+ * someone else might change some whiteouts while we were sleeping.
35847+ * it means this whlist may have an obsoleted entry.
35848+ */
35849+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
35850+ err = del_wh_children(wh_dentry, whlist, bindex, br);
35851+ else {
35852+ int wkq_err;
35853+ struct del_wh_children_args args = {
35854+ .errp = &err,
35855+ .h_dentry = wh_dentry,
1308ab2a 35856+ .whlist = whlist,
1facf9fc 35857+ .bindex = bindex,
35858+ .br = br
35859+ };
35860+
35861+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
35862+ if (unlikely(wkq_err))
35863+ err = wkq_err;
35864+ }
febd17d6 35865+ inode_unlock(wh_inode);
1facf9fc 35866+
35867+ if (!err) {
35868+ h_tmp.dentry = wh_dentry;
86dc4139 35869+ h_tmp.mnt = au_br_mnt(br);
2000de60 35870+ h_nlink = h_dir->i_nlink;
1facf9fc 35871+ err = vfsub_rmdir(h_dir, &h_tmp);
2000de60
JR
35872+ /* some fs doesn't change the parent nlink in some cases */
35873+ h_nlink -= h_dir->i_nlink;
1facf9fc 35874+ }
35875+
35876+ if (!err) {
5afbbe0d 35877+ if (au_ibtop(dir) == bindex) {
7f207e10 35878+ /* todo: dir->i_mutex is necessary */
1facf9fc 35879+ au_cpup_attr_timesizes(dir);
2000de60
JR
35880+ if (h_nlink)
35881+ vfsub_drop_nlink(dir);
1facf9fc 35882+ }
35883+ return 0; /* success */
35884+ }
35885+
523b37e3 35886+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err);
1facf9fc 35887+ return err;
35888+}
35889+
35890+static void call_rmdir_whtmp(void *args)
35891+{
35892+ int err;
e49829fe 35893+ aufs_bindex_t bindex;
1facf9fc 35894+ struct au_whtmp_rmdir *a = args;
35895+ struct super_block *sb;
35896+ struct dentry *h_parent;
35897+ struct inode *h_dir;
1facf9fc 35898+ struct au_hinode *hdir;
35899+
35900+ /* rmdir by nfsd may cause deadlock with this i_mutex */
febd17d6 35901+ /* inode_lock(a->dir); */
e49829fe 35902+ err = -EROFS;
1facf9fc 35903+ sb = a->dir->i_sb;
e49829fe
JR
35904+ si_read_lock(sb, !AuLock_FLUSH);
35905+ if (!au_br_writable(a->br->br_perm))
35906+ goto out;
35907+ bindex = au_br_index(sb, a->br->br_id);
35908+ if (unlikely(bindex < 0))
1facf9fc 35909+ goto out;
35910+
35911+ err = -EIO;
1facf9fc 35912+ ii_write_lock_parent(a->dir);
35913+ h_parent = dget_parent(a->wh_dentry);
5527c038 35914+ h_dir = d_inode(h_parent);
e49829fe 35915+ hdir = au_hi(a->dir, bindex);
86dc4139
AM
35916+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
35917+ if (unlikely(err))
35918+ goto out_mnt;
5afbbe0d 35919+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
35920+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
35921+ a->br);
86dc4139
AM
35922+ if (!err)
35923+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist);
5afbbe0d 35924+ au_hn_inode_unlock(hdir);
86dc4139
AM
35925+ vfsub_mnt_drop_write(au_br_mnt(a->br));
35926+
35927+out_mnt:
1facf9fc 35928+ dput(h_parent);
35929+ ii_write_unlock(a->dir);
4f0767ce 35930+out:
febd17d6 35931+ /* inode_unlock(a->dir); */
1facf9fc 35932+ au_whtmp_rmdir_free(a);
027c5e7a
AM
35933+ si_read_unlock(sb);
35934+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 35935+ if (unlikely(err))
35936+ AuIOErr("err %d\n", err);
35937+}
35938+
35939+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
35940+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
35941+{
35942+ int wkq_err;
e49829fe 35943+ struct super_block *sb;
1facf9fc 35944+
35945+ IMustLock(dir);
35946+
35947+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 35948+ sb = dir->i_sb;
1facf9fc 35949+ args->dir = au_igrab(dir);
e49829fe 35950+ args->br = au_sbr(sb, bindex);
acd2b654 35951+ au_lcnt_inc(&args->br->br_count);
1facf9fc 35952+ args->wh_dentry = dget(wh_dentry);
53392da6 35953+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 35954+ if (unlikely(wkq_err)) {
523b37e3 35955+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err);
1facf9fc 35956+ au_whtmp_rmdir_free(args);
35957+ }
35958+}
7f207e10 35959diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
fbc438ed
JR
35960--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 08:00:00.000000000 +0800
35961+++ linux/fs/aufs/whout.h 2019-07-11 21:21:54.382384486 +0800
062440b3
AM
35962@@ -0,0 +1,86 @@
35963+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 35964+/*
ba1aed25 35965+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 35966+ *
35967+ * This program, aufs is free software; you can redistribute it and/or modify
35968+ * it under the terms of the GNU General Public License as published by
35969+ * the Free Software Foundation; either version 2 of the License, or
35970+ * (at your option) any later version.
dece6358
AM
35971+ *
35972+ * This program is distributed in the hope that it will be useful,
35973+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35974+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35975+ * GNU General Public License for more details.
35976+ *
35977+ * You should have received a copy of the GNU General Public License
523b37e3 35978+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35979+ */
35980+
35981+/*
35982+ * whiteout for logical deletion and opaque directory
35983+ */
35984+
35985+#ifndef __AUFS_WHOUT_H__
35986+#define __AUFS_WHOUT_H__
35987+
35988+#ifdef __KERNEL__
35989+
1facf9fc 35990+#include "dir.h"
35991+
35992+/* whout.c */
35993+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
076b876e
AM
35994+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio);
35995+int au_diropq_test(struct dentry *h_dentry);
3c1bdaff 35996+struct au_branch;
1facf9fc 35997+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
35998+ struct qstr *prefix);
35999+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
36000+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
36001+ struct dentry *dentry);
86dc4139 36002+int au_wh_init(struct au_branch *br, struct super_block *sb);
1facf9fc 36003+
36004+/* diropq flags */
36005+#define AuDiropq_CREATE 1
36006+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
36007+#define au_fset_diropq(flags, name) \
36008+ do { (flags) |= AuDiropq_##name; } while (0)
36009+#define au_fclr_diropq(flags, name) \
36010+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 36011+
36012+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
36013+ unsigned int flags);
36014+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
36015+ struct au_branch *br);
36016+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
36017+ struct dentry *h_parent);
36018+
36019+/* real rmdir for the whiteout-ed dir */
36020+struct au_whtmp_rmdir {
36021+ struct inode *dir;
e49829fe 36022+ struct au_branch *br;
1facf9fc 36023+ struct dentry *wh_dentry;
dece6358 36024+ struct au_nhash whlist;
1facf9fc 36025+};
36026+
36027+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
36028+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
36029+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
36030+ struct dentry *wh_dentry, struct au_nhash *whlist);
36031+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
36032+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
36033+
36034+/* ---------------------------------------------------------------------- */
36035+
36036+static inline struct dentry *au_diropq_create(struct dentry *dentry,
36037+ aufs_bindex_t bindex)
36038+{
36039+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
36040+}
36041+
36042+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
36043+{
36044+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
36045+}
36046+
36047+#endif /* __KERNEL__ */
36048+#endif /* __AUFS_WHOUT_H__ */
7f207e10 36049diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
fbc438ed
JR
36050--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 08:00:00.000000000 +0800
36051+++ linux/fs/aufs/wkq.c 2019-07-11 21:21:54.382384486 +0800
acd2b654 36052@@ -0,0 +1,392 @@
cd7a4cd9 36053+// SPDX-License-Identifier: GPL-2.0
1facf9fc 36054+/*
ba1aed25 36055+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 36056+ *
36057+ * This program, aufs is free software; you can redistribute it and/or modify
36058+ * it under the terms of the GNU General Public License as published by
36059+ * the Free Software Foundation; either version 2 of the License, or
36060+ * (at your option) any later version.
dece6358
AM
36061+ *
36062+ * This program is distributed in the hope that it will be useful,
36063+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36064+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36065+ * GNU General Public License for more details.
36066+ *
36067+ * You should have received a copy of the GNU General Public License
523b37e3 36068+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36069+ */
36070+
36071+/*
36072+ * workqueue for asynchronous/super-io operations
acd2b654 36073+ * todo: try new credential scheme
1facf9fc 36074+ */
36075+
dece6358 36076+#include <linux/module.h>
1facf9fc 36077+#include "aufs.h"
36078+
9dbd164d 36079+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 36080+
9dbd164d 36081+static struct workqueue_struct *au_wkq;
1facf9fc 36082+
36083+struct au_wkinfo {
36084+ struct work_struct wk;
7f207e10 36085+ struct kobject *kobj;
1facf9fc 36086+
36087+ unsigned int flags; /* see wkq.h */
36088+
36089+ au_wkq_func_t func;
36090+ void *args;
36091+
8b6a4947
AM
36092+#ifdef CONFIG_LOCKDEP
36093+ int dont_check;
36094+ struct held_lock **hlock;
36095+#endif
36096+
1facf9fc 36097+ struct completion *comp;
36098+};
36099+
36100+/* ---------------------------------------------------------------------- */
8b6a4947
AM
36101+/*
36102+ * Aufs passes some operations to the workqueue such as the internal copyup.
36103+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the
36104+ * job run by workqueue depends upon the locks acquired in the other task.
36105+ * Delegating a small operation to the workqueue, aufs passes its lockdep
36106+ * information too. And the job in the workqueue restores the info in order to
36107+ * pretend as if it acquired those locks. This is just to make LOCKDEP work
36108+ * correctly and expectedly.
36109+ */
36110+
36111+#ifndef CONFIG_LOCKDEP
36112+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo);
36113+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo);
36114+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo);
36115+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo);
36116+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo);
36117+#else
36118+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo)
36119+{
36120+ wkinfo->hlock = NULL;
36121+ wkinfo->dont_check = 0;
36122+}
36123+
36124+/*
36125+ * 1: matched
36126+ * 0: unmatched
36127+ */
36128+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name)
36129+{
36130+ static DEFINE_SPINLOCK(spin);
36131+ static struct {
36132+ char *name;
36133+ struct lock_class_key *key;
36134+ } a[] = {
36135+ { .name = "&sbinfo->si_rwsem" },
36136+ { .name = "&finfo->fi_rwsem" },
36137+ { .name = "&dinfo->di_rwsem" },
36138+ { .name = "&iinfo->ii_rwsem" }
36139+ };
36140+ static int set;
36141+ int i;
36142+
36143+ /* lockless read from 'set.' see below */
36144+ if (set == ARRAY_SIZE(a)) {
36145+ for (i = 0; i < ARRAY_SIZE(a); i++)
36146+ if (a[i].key == key)
36147+ goto match;
36148+ goto unmatch;
36149+ }
36150+
36151+ spin_lock(&spin);
36152+ if (set)
36153+ for (i = 0; i < ARRAY_SIZE(a); i++)
36154+ if (a[i].key == key) {
36155+ spin_unlock(&spin);
36156+ goto match;
36157+ }
36158+ for (i = 0; i < ARRAY_SIZE(a); i++) {
36159+ if (a[i].key) {
36160+ if (unlikely(a[i].key == key)) { /* rare but possible */
36161+ spin_unlock(&spin);
36162+ goto match;
36163+ } else
36164+ continue;
36165+ }
36166+ if (strstr(a[i].name, name)) {
36167+ /*
36168+ * the order of these three lines is important for the
36169+ * lockless read above.
36170+ */
36171+ a[i].key = key;
36172+ spin_unlock(&spin);
36173+ set++;
36174+ /* AuDbg("%d, %s\n", set, name); */
36175+ goto match;
36176+ }
36177+ }
36178+ spin_unlock(&spin);
36179+ goto unmatch;
36180+
36181+match:
36182+ return 1;
36183+unmatch:
36184+ return 0;
36185+}
36186+
36187+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo)
36188+{
36189+ int err, n;
36190+ struct task_struct *curr;
36191+ struct held_lock **hl, *held_locks, *p;
36192+
36193+ err = 0;
36194+ curr = current;
36195+ wkinfo->dont_check = lockdep_recursing(curr);
36196+ if (wkinfo->dont_check)
36197+ goto out;
36198+ n = curr->lockdep_depth;
36199+ if (!n)
36200+ goto out;
36201+
36202+ err = -ENOMEM;
36203+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS);
36204+ if (unlikely(!wkinfo->hlock))
36205+ goto out;
36206+
36207+ err = 0;
36208+#if 0
36209+ if (0 && au_debug_test()) /* left for debugging */
36210+ lockdep_print_held_locks(curr);
36211+#endif
36212+ held_locks = curr->held_locks;
36213+ hl = wkinfo->hlock;
36214+ while (n--) {
36215+ p = held_locks++;
36216+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name))
36217+ *hl++ = p;
36218+ }
36219+ *hl = NULL;
36220+
36221+out:
36222+ return err;
36223+}
36224+
36225+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo)
36226+{
9f237c51 36227+ au_kfree_try_rcu(wkinfo->hlock);
8b6a4947
AM
36228+}
36229+
36230+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo)
36231+{
36232+ struct held_lock *p, **hl = wkinfo->hlock;
36233+ int subclass;
36234+
36235+ if (wkinfo->dont_check)
36236+ lockdep_off();
36237+ if (!hl)
36238+ return;
36239+ while ((p = *hl++)) { /* assignment */
36240+ subclass = lockdep_hlock_class(p)->subclass;
36241+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */
36242+ if (p->read)
36243+ rwsem_acquire_read(p->instance, subclass, 0,
36244+ /*p->acquire_ip*/_RET_IP_);
36245+ else
36246+ rwsem_acquire(p->instance, subclass, 0,
36247+ /*p->acquire_ip*/_RET_IP_);
36248+ }
36249+}
36250+
36251+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo)
36252+{
36253+ struct held_lock *p, **hl = wkinfo->hlock;
36254+
36255+ if (wkinfo->dont_check)
36256+ lockdep_on();
36257+ if (!hl)
36258+ return;
36259+ while ((p = *hl++)) /* assignment */
36260+ rwsem_release(p->instance, 0, /*p->acquire_ip*/_RET_IP_);
36261+}
36262+#endif
1facf9fc 36263+
1facf9fc 36264+static void wkq_func(struct work_struct *wk)
36265+{
36266+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
36267+
2dfbb274 36268+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
36269+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
36270+
8b6a4947 36271+ au_wkq_lockdep_pre(wkinfo);
1facf9fc 36272+ wkinfo->func(wkinfo->args);
8b6a4947 36273+ au_wkq_lockdep_post(wkinfo);
1facf9fc 36274+ if (au_ftest_wkq(wkinfo->flags, WAIT))
36275+ complete(wkinfo->comp);
36276+ else {
7f207e10 36277+ kobject_put(wkinfo->kobj);
9dbd164d 36278+ module_put(THIS_MODULE); /* todo: ?? */
9f237c51 36279+ au_kfree_rcu(wkinfo);
1facf9fc 36280+ }
36281+}
36282+
36283+/*
36284+ * Since struct completion is large, try allocating it dynamically.
36285+ */
c2b27bf2 36286+#if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */
1facf9fc 36287+#define AuWkqCompDeclare(name) struct completion *comp = NULL
36288+
36289+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
36290+{
36291+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
36292+ if (*comp) {
36293+ init_completion(*comp);
36294+ wkinfo->comp = *comp;
36295+ return 0;
36296+ }
36297+ return -ENOMEM;
36298+}
36299+
36300+static void au_wkq_comp_free(struct completion *comp)
36301+{
9f237c51 36302+ au_kfree_rcu(comp);
1facf9fc 36303+}
36304+
36305+#else
36306+
36307+/* no braces */
36308+#define AuWkqCompDeclare(name) \
36309+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
36310+ struct completion *comp = &_ ## name
36311+
36312+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
36313+{
36314+ wkinfo->comp = *comp;
36315+ return 0;
36316+}
36317+
36318+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
36319+{
36320+ /* empty */
36321+}
36322+#endif /* 4KSTACKS */
36323+
53392da6 36324+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 36325+{
53392da6
AM
36326+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
36327+ if (au_wkq_test()) {
38d290e6 36328+ AuWarn1("wkq from wkq, unless silly-rename on NFS,"
acd2b654
AM
36329+ " due to a dead dir by UDBA,"
36330+ " or async xino write?\n");
53392da6
AM
36331+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
36332+ }
36333+ } else
36334+ au_dbg_verify_kthread();
36335+
36336+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 36337+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 36338+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
36339+ } else {
36340+ INIT_WORK(&wkinfo->wk, wkq_func);
36341+ schedule_work(&wkinfo->wk);
36342+ }
1facf9fc 36343+}
36344+
7f207e10
AM
36345+/*
36346+ * Be careful. It is easy to make deadlock happen.
36347+ * processA: lock, wkq and wait
36348+ * processB: wkq and wait, lock in wkq
36349+ * --> deadlock
36350+ */
b752ccd1 36351+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 36352+{
36353+ int err;
36354+ AuWkqCompDeclare(comp);
36355+ struct au_wkinfo wkinfo = {
b752ccd1 36356+ .flags = flags,
1facf9fc 36357+ .func = func,
36358+ .args = args
36359+ };
36360+
36361+ err = au_wkq_comp_alloc(&wkinfo, &comp);
8b6a4947
AM
36362+ if (unlikely(err))
36363+ goto out;
36364+ err = au_wkq_lockdep_alloc(&wkinfo);
36365+ if (unlikely(err))
36366+ goto out_comp;
1facf9fc 36367+ if (!err) {
53392da6 36368+ au_wkq_run(&wkinfo);
1facf9fc 36369+ /* no timeout, no interrupt */
36370+ wait_for_completion(wkinfo.comp);
1facf9fc 36371+ }
8b6a4947 36372+ au_wkq_lockdep_free(&wkinfo);
1facf9fc 36373+
8b6a4947
AM
36374+out_comp:
36375+ au_wkq_comp_free(comp);
36376+out:
36377+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 36378+ return err;
1facf9fc 36379+}
36380+
027c5e7a
AM
36381+/*
36382+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
36383+ * problem in a concurrent umounting.
36384+ */
53392da6
AM
36385+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36386+ unsigned int flags)
1facf9fc 36387+{
36388+ int err;
36389+ struct au_wkinfo *wkinfo;
36390+
f0c0a007 36391+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
1facf9fc 36392+
36393+ /*
36394+ * wkq_func() must free this wkinfo.
36395+ * it highly depends upon the implementation of workqueue.
36396+ */
36397+ err = 0;
36398+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
36399+ if (wkinfo) {
7f207e10 36400+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 36401+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 36402+ wkinfo->func = func;
36403+ wkinfo->args = args;
36404+ wkinfo->comp = NULL;
8b6a4947 36405+ au_wkq_lockdep_init(wkinfo);
7f207e10 36406+ kobject_get(wkinfo->kobj);
9dbd164d 36407+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 36408+
53392da6 36409+ au_wkq_run(wkinfo);
1facf9fc 36410+ } else {
36411+ err = -ENOMEM;
e49829fe 36412+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 36413+ }
36414+
36415+ return err;
36416+}
36417+
36418+/* ---------------------------------------------------------------------- */
36419+
36420+void au_nwt_init(struct au_nowait_tasks *nwt)
36421+{
f0c0a007
AM
36422+ atomic_set(&nwt->nw_len, 0);
36423+ /* smp_mb(); */ /* atomic_set */
1facf9fc 36424+ init_waitqueue_head(&nwt->nw_wq);
36425+}
36426+
36427+void au_wkq_fin(void)
36428+{
9dbd164d 36429+ destroy_workqueue(au_wkq);
1facf9fc 36430+}
36431+
36432+int __init au_wkq_init(void)
36433+{
9dbd164d 36434+ int err;
b752ccd1
AM
36435+
36436+ err = 0;
86dc4139 36437+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE);
9dbd164d
AM
36438+ if (IS_ERR(au_wkq))
36439+ err = PTR_ERR(au_wkq);
36440+ else if (!au_wkq)
36441+ err = -ENOMEM;
b752ccd1
AM
36442+
36443+ return err;
1facf9fc 36444+}
7f207e10 36445diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
fbc438ed
JR
36446--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 08:00:00.000000000 +0800
36447+++ linux/fs/aufs/wkq.h 2019-07-11 21:21:54.382384486 +0800
acd2b654 36448@@ -0,0 +1,89 @@
062440b3 36449+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 36450+/*
ba1aed25 36451+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 36452+ *
36453+ * This program, aufs is free software; you can redistribute it and/or modify
36454+ * it under the terms of the GNU General Public License as published by
36455+ * the Free Software Foundation; either version 2 of the License, or
36456+ * (at your option) any later version.
dece6358
AM
36457+ *
36458+ * This program is distributed in the hope that it will be useful,
36459+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36460+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36461+ * GNU General Public License for more details.
36462+ *
36463+ * You should have received a copy of the GNU General Public License
523b37e3 36464+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36465+ */
36466+
36467+/*
36468+ * workqueue for asynchronous/super-io operations
36469+ * todo: try new credentials management scheme
36470+ */
36471+
36472+#ifndef __AUFS_WKQ_H__
36473+#define __AUFS_WKQ_H__
36474+
36475+#ifdef __KERNEL__
36476+
8b6a4947 36477+#include <linux/wait.h>
5afbbe0d 36478+
dece6358
AM
36479+struct super_block;
36480+
1facf9fc 36481+/* ---------------------------------------------------------------------- */
36482+
36483+/*
36484+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
36485+ */
36486+struct au_nowait_tasks {
f0c0a007 36487+ atomic_t nw_len;
1facf9fc 36488+ wait_queue_head_t nw_wq;
36489+};
36490+
36491+/* ---------------------------------------------------------------------- */
36492+
36493+typedef void (*au_wkq_func_t)(void *args);
36494+
36495+/* wkq flags */
36496+#define AuWkq_WAIT 1
9dbd164d 36497+#define AuWkq_NEST (1 << 1)
1facf9fc 36498+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
36499+#define au_fset_wkq(flags, name) \
36500+ do { (flags) |= AuWkq_##name; } while (0)
36501+#define au_fclr_wkq(flags, name) \
36502+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 36503+
36504+/* wkq.c */
b752ccd1 36505+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
36506+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36507+ unsigned int flags);
1facf9fc 36508+void au_nwt_init(struct au_nowait_tasks *nwt);
36509+int __init au_wkq_init(void);
36510+void au_wkq_fin(void);
36511+
36512+/* ---------------------------------------------------------------------- */
36513+
53392da6
AM
36514+static inline int au_wkq_test(void)
36515+{
36516+ return current->flags & PF_WQ_WORKER;
36517+}
36518+
b752ccd1 36519+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 36520+{
b752ccd1 36521+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 36522+}
36523+
36524+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
36525+{
f0c0a007 36526+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 36527+ wake_up_all(&nwt->nw_wq);
36528+}
36529+
36530+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
36531+{
f0c0a007 36532+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
1facf9fc 36533+ return 0;
36534+}
36535+
36536+#endif /* __KERNEL__ */
36537+#endif /* __AUFS_WKQ_H__ */
c1595e42 36538diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c
fbc438ed
JR
36539--- /usr/share/empty/fs/aufs/xattr.c 1970-01-01 08:00:00.000000000 +0800
36540+++ linux/fs/aufs/xattr.c 2019-07-11 21:21:54.382384486 +0800
062440b3 36541@@ -0,0 +1,356 @@
cd7a4cd9 36542+// SPDX-License-Identifier: GPL-2.0
c1595e42 36543+/*
ba1aed25 36544+ * Copyright (C) 2014-2019 Junjiro R. Okajima
c1595e42
JR
36545+ *
36546+ * This program, aufs is free software; you can redistribute it and/or modify
36547+ * it under the terms of the GNU General Public License as published by
36548+ * the Free Software Foundation; either version 2 of the License, or
36549+ * (at your option) any later version.
36550+ *
36551+ * This program is distributed in the hope that it will be useful,
36552+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36553+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36554+ * GNU General Public License for more details.
36555+ *
36556+ * You should have received a copy of the GNU General Public License
36557+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
36558+ */
36559+
36560+/*
36561+ * handling xattr functions
36562+ */
36563+
a2654f78
AM
36564+#include <linux/fs.h>
36565+#include <linux/posix_acl_xattr.h>
c1595e42
JR
36566+#include <linux/xattr.h>
36567+#include "aufs.h"
36568+
36569+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
36570+{
36571+ if (!ignore_flags)
36572+ goto out;
36573+ switch (err) {
36574+ case -ENOMEM:
36575+ case -EDQUOT:
36576+ goto out;
36577+ }
36578+
36579+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
36580+ err = 0;
36581+ goto out;
36582+ }
36583+
36584+#define cmp(brattr, prefix) do { \
36585+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \
36586+ XATTR_##prefix##_PREFIX_LEN)) { \
36587+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \
36588+ err = 0; \
36589+ goto out; \
36590+ } \
36591+ } while (0)
36592+
36593+ cmp(SEC, SECURITY);
36594+ cmp(SYS, SYSTEM);
36595+ cmp(TR, TRUSTED);
36596+ cmp(USR, USER);
36597+#undef cmp
36598+
36599+ if (ignore_flags & AuBrAttr_ICEX_OTH)
36600+ err = 0;
36601+
36602+out:
36603+ return err;
36604+}
36605+
36606+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
36607+
36608+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
7e9cd9fe
AM
36609+ char *name, char **buf, unsigned int ignore_flags,
36610+ unsigned int verbose)
c1595e42
JR
36611+{
36612+ int err;
36613+ ssize_t ssz;
36614+ struct inode *h_idst;
36615+
36616+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS);
36617+ err = ssz;
36618+ if (unlikely(err <= 0)) {
c1595e42
JR
36619+ if (err == -ENODATA
36620+ || (err == -EOPNOTSUPP
b912730e 36621+ && ((ignore_flags & au_xattr_out_of_list)
5527c038 36622+ || (au_test_nfs_noacl(d_inode(h_src))
b912730e
AM
36623+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
36624+ || !strcmp(name,
36625+ XATTR_NAME_POSIX_ACL_DEFAULT))))
36626+ ))
c1595e42 36627+ err = 0;
b912730e
AM
36628+ if (err && (verbose || au_debug_test()))
36629+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36630+ goto out;
36631+ }
36632+
36633+ /* unlock it temporary */
5527c038 36634+ h_idst = d_inode(h_dst);
febd17d6 36635+ inode_unlock(h_idst);
c1595e42 36636+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0);
febd17d6 36637+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42 36638+ if (unlikely(err)) {
7e9cd9fe
AM
36639+ if (verbose || au_debug_test())
36640+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36641+ err = au_xattr_ignore(err, name, ignore_flags);
36642+ }
36643+
36644+out:
36645+ return err;
36646+}
36647+
7e9cd9fe
AM
36648+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
36649+ unsigned int verbose)
c1595e42
JR
36650+{
36651+ int err, unlocked, acl_access, acl_default;
36652+ ssize_t ssz;
36653+ struct inode *h_isrc, *h_idst;
36654+ char *value, *p, *o, *e;
36655+
36656+ /* try stopping to update the source inode while we are referencing */
7e9cd9fe 36657+ /* there should not be the parent-child relationship between them */
5527c038
JR
36658+ h_isrc = d_inode(h_src);
36659+ h_idst = d_inode(h_dst);
febd17d6 36660+ inode_unlock(h_idst);
be118d29 36661+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD);
febd17d6 36662+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42
JR
36663+ unlocked = 0;
36664+
36665+ /* some filesystems don't list POSIX ACL, for example tmpfs */
36666+ ssz = vfs_listxattr(h_src, NULL, 0);
36667+ err = ssz;
36668+ if (unlikely(err < 0)) {
36669+ AuTraceErr(err);
36670+ if (err == -ENODATA
36671+ || err == -EOPNOTSUPP)
36672+ err = 0; /* ignore */
36673+ goto out;
36674+ }
36675+
36676+ err = 0;
36677+ p = NULL;
36678+ o = NULL;
36679+ if (ssz) {
36680+ err = -ENOMEM;
36681+ p = kmalloc(ssz, GFP_NOFS);
36682+ o = p;
36683+ if (unlikely(!p))
36684+ goto out;
36685+ err = vfs_listxattr(h_src, p, ssz);
36686+ }
3c1bdaff 36687+ inode_unlock_shared(h_isrc);
c1595e42
JR
36688+ unlocked = 1;
36689+ AuDbg("err %d, ssz %zd\n", err, ssz);
36690+ if (unlikely(err < 0))
36691+ goto out_free;
36692+
36693+ err = 0;
36694+ e = p + ssz;
36695+ value = NULL;
36696+ acl_access = 0;
36697+ acl_default = 0;
36698+ while (!err && p < e) {
36699+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
36700+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
36701+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
36702+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
36703+ - 1);
7e9cd9fe
AM
36704+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
36705+ verbose);
c1595e42
JR
36706+ p += strlen(p) + 1;
36707+ }
36708+ AuTraceErr(err);
36709+ ignore_flags |= au_xattr_out_of_list;
36710+ if (!err && !acl_access) {
36711+ err = au_do_cpup_xattr(h_dst, h_src,
36712+ XATTR_NAME_POSIX_ACL_ACCESS, &value,
7e9cd9fe 36713+ ignore_flags, verbose);
c1595e42
JR
36714+ AuTraceErr(err);
36715+ }
36716+ if (!err && !acl_default) {
36717+ err = au_do_cpup_xattr(h_dst, h_src,
36718+ XATTR_NAME_POSIX_ACL_DEFAULT, &value,
7e9cd9fe 36719+ ignore_flags, verbose);
c1595e42
JR
36720+ AuTraceErr(err);
36721+ }
36722+
9f237c51 36723+ au_kfree_try_rcu(value);
c1595e42
JR
36724+
36725+out_free:
9f237c51 36726+ au_kfree_try_rcu(o);
c1595e42
JR
36727+out:
36728+ if (!unlocked)
3c1bdaff 36729+ inode_unlock_shared(h_isrc);
c1595e42
JR
36730+ AuTraceErr(err);
36731+ return err;
36732+}
36733+
36734+/* ---------------------------------------------------------------------- */
36735+
a2654f78
AM
36736+static int au_smack_reentering(struct super_block *sb)
36737+{
36738+#if IS_ENABLED(CONFIG_SECURITY_SMACK)
36739+ /*
36740+ * as a part of lookup, smack_d_instantiate() is called, and it calls
36741+ * i_op->getxattr(). ouch.
36742+ */
36743+ return si_pid_test(sb);
36744+#else
36745+ return 0;
36746+#endif
36747+}
36748+
c1595e42
JR
36749+enum {
36750+ AU_XATTR_LIST,
36751+ AU_XATTR_GET
36752+};
36753+
36754+struct au_lgxattr {
36755+ int type;
36756+ union {
36757+ struct {
36758+ char *list;
36759+ size_t size;
36760+ } list;
36761+ struct {
36762+ const char *name;
36763+ void *value;
36764+ size_t size;
36765+ } get;
36766+ } u;
36767+};
36768+
36769+static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg)
36770+{
36771+ ssize_t err;
a2654f78 36772+ int reenter;
c1595e42
JR
36773+ struct path h_path;
36774+ struct super_block *sb;
36775+
36776+ sb = dentry->d_sb;
a2654f78
AM
36777+ reenter = au_smack_reentering(sb);
36778+ if (!reenter) {
36779+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
36780+ if (unlikely(err))
36781+ goto out;
36782+ }
36783+ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter);
c1595e42
JR
36784+ if (unlikely(err))
36785+ goto out_si;
36786+ if (unlikely(!h_path.dentry))
36787+ /* illegally overlapped or something */
36788+ goto out_di; /* pretending success */
36789+
36790+ /* always topmost entry only */
36791+ switch (arg->type) {
36792+ case AU_XATTR_LIST:
36793+ err = vfs_listxattr(h_path.dentry,
36794+ arg->u.list.list, arg->u.list.size);
36795+ break;
36796+ case AU_XATTR_GET:
5afbbe0d 36797+ AuDebugOn(d_is_negative(h_path.dentry));
c1595e42
JR
36798+ err = vfs_getxattr(h_path.dentry,
36799+ arg->u.get.name, arg->u.get.value,
36800+ arg->u.get.size);
36801+ break;
36802+ }
36803+
36804+out_di:
a2654f78
AM
36805+ if (!reenter)
36806+ di_read_unlock(dentry, AuLock_IR);
c1595e42 36807+out_si:
a2654f78
AM
36808+ if (!reenter)
36809+ si_read_unlock(sb);
c1595e42
JR
36810+out:
36811+ AuTraceErr(err);
36812+ return err;
36813+}
36814+
36815+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
36816+{
36817+ struct au_lgxattr arg = {
36818+ .type = AU_XATTR_LIST,
36819+ .u.list = {
36820+ .list = list,
36821+ .size = size
36822+ },
36823+ };
36824+
36825+ return au_lgxattr(dentry, &arg);
36826+}
36827+
f2c43d5f
AM
36828+static ssize_t au_getxattr(struct dentry *dentry,
36829+ struct inode *inode __maybe_unused,
36830+ const char *name, void *value, size_t size)
c1595e42
JR
36831+{
36832+ struct au_lgxattr arg = {
36833+ .type = AU_XATTR_GET,
36834+ .u.get = {
36835+ .name = name,
36836+ .value = value,
36837+ .size = size
36838+ },
36839+ };
36840+
36841+ return au_lgxattr(dentry, &arg);
36842+}
36843+
f2c43d5f
AM
36844+static int au_setxattr(struct dentry *dentry, struct inode *inode,
36845+ const char *name, const void *value, size_t size,
36846+ int flags)
c1595e42 36847+{
f2c43d5f 36848+ struct au_sxattr arg = {
c1595e42
JR
36849+ .type = AU_XATTR_SET,
36850+ .u.set = {
36851+ .name = name,
36852+ .value = value,
36853+ .size = size,
36854+ .flags = flags
36855+ },
36856+ };
36857+
f2c43d5f 36858+ return au_sxattr(dentry, inode, &arg);
c1595e42
JR
36859+}
36860+
36861+/* ---------------------------------------------------------------------- */
36862+
f2c43d5f
AM
36863+static int au_xattr_get(const struct xattr_handler *handler,
36864+ struct dentry *dentry, struct inode *inode,
36865+ const char *name, void *buffer, size_t size)
c1595e42 36866+{
f2c43d5f 36867+ return au_getxattr(dentry, inode, name, buffer, size);
c1595e42
JR
36868+}
36869+
f2c43d5f
AM
36870+static int au_xattr_set(const struct xattr_handler *handler,
36871+ struct dentry *dentry, struct inode *inode,
36872+ const char *name, const void *value, size_t size,
36873+ int flags)
c1595e42 36874+{
f2c43d5f 36875+ return au_setxattr(dentry, inode, name, value, size, flags);
c1595e42
JR
36876+}
36877+
36878+static const struct xattr_handler au_xattr_handler = {
f2c43d5f
AM
36879+ .name = "",
36880+ .prefix = "",
c1595e42
JR
36881+ .get = au_xattr_get,
36882+ .set = au_xattr_set
c1595e42
JR
36883+};
36884+
36885+static const struct xattr_handler *au_xattr_handlers[] = {
a2654f78
AM
36886+#ifdef CONFIG_FS_POSIX_ACL
36887+ &posix_acl_access_xattr_handler,
36888+ &posix_acl_default_xattr_handler,
36889+#endif
36890+ &au_xattr_handler, /* must be last */
f2c43d5f 36891+ NULL
c1595e42
JR
36892+};
36893+
36894+void au_xattr_init(struct super_block *sb)
36895+{
f2c43d5f 36896+ sb->s_xattr = au_xattr_handlers;
c1595e42 36897+}
7f207e10 36898diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
fbc438ed
JR
36899--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 08:00:00.000000000 +0800
36900+++ linux/fs/aufs/xino.c 2019-07-11 21:21:54.382384486 +0800
83b672a5 36901@@ -0,0 +1,1965 @@
cd7a4cd9 36902+// SPDX-License-Identifier: GPL-2.0
1facf9fc 36903+/*
ba1aed25 36904+ * Copyright (C) 2005-2019 Junjiro R. Okajima
1facf9fc 36905+ *
36906+ * This program, aufs is free software; you can redistribute it and/or modify
36907+ * it under the terms of the GNU General Public License as published by
36908+ * the Free Software Foundation; either version 2 of the License, or
36909+ * (at your option) any later version.
dece6358
AM
36910+ *
36911+ * This program is distributed in the hope that it will be useful,
36912+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36913+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36914+ * GNU General Public License for more details.
36915+ *
36916+ * You should have received a copy of the GNU General Public License
523b37e3 36917+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36918+ */
36919+
36920+/*
36921+ * external inode number translation table and bitmap
062440b3
AM
36922+ *
36923+ * things to consider
36924+ * - the lifetime
36925+ * + au_xino object
36926+ * + XINO files (xino, xib, xigen)
36927+ * + dynamic debugfs entries (xiN)
36928+ * + static debugfs entries (xib, xigen)
36929+ * + static sysfs entry (xi_path)
36930+ * - several entry points to handle them.
36931+ * + mount(2) without xino option (default)
36932+ * + mount(2) with xino option
36933+ * + mount(2) with noxino option
36934+ * + umount(2)
36935+ * + remount with add/del branches
36936+ * + remount with xino/noxino options
1facf9fc 36937+ */
36938+
36939+#include <linux/seq_file.h>
392086de 36940+#include <linux/statfs.h>
1facf9fc 36941+#include "aufs.h"
36942+
062440b3
AM
36943+static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop,
36944+ aufs_bindex_t bbot,
36945+ struct super_block *h_sb)
1facf9fc 36946+{
062440b3
AM
36947+ /* todo: try binary-search if the branches are many */
36948+ for (; btop <= bbot; btop++)
36949+ if (h_sb == au_sbr_sb(sb, btop))
36950+ return btop;
36951+ return -1;
be52b249
AM
36952+}
36953+
062440b3
AM
36954+/*
36955+ * find another branch who is on the same filesystem of the specified
36956+ * branch{@btgt}. search until @bbot.
36957+ */
36958+static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
36959+ aufs_bindex_t bbot)
1facf9fc 36960+{
062440b3
AM
36961+ aufs_bindex_t bindex;
36962+ struct super_block *tgt_sb;
1facf9fc 36963+
062440b3
AM
36964+ tgt_sb = au_sbr_sb(sb, btgt);
36965+ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb);
36966+ if (bindex < 0)
36967+ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb);
1facf9fc 36968+
062440b3 36969+ return bindex;
1facf9fc 36970+}
36971+
36972+/* ---------------------------------------------------------------------- */
36973+
36974+/*
062440b3 36975+ * stop unnecessary notify events at creating xino files
1facf9fc 36976+ */
acd2b654
AM
36977+
36978+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry)
36979+{
36980+ aufs_bindex_t bfound, bindex, bbot;
36981+ struct dentry *parent;
36982+ struct au_branch *br;
36983+
36984+ bfound = -1;
36985+ parent = dentry->d_parent; /* safe d_parent access */
36986+ bbot = au_sbbot(sb);
36987+ for (bindex = 0; bindex <= bbot; bindex++) {
36988+ br = au_sbr(sb, bindex);
36989+ if (au_br_dentry(br) == parent) {
36990+ bfound = bindex;
36991+ break;
36992+ }
36993+ }
36994+
36995+ AuDbg("bfound b%d\n", bfound);
36996+ return bfound;
36997+}
36998+
062440b3
AM
36999+struct au_xino_lock_dir {
37000+ struct au_hinode *hdir;
37001+ struct dentry *parent;
37002+ struct inode *dir;
37003+};
37004+
37005+static struct dentry *au_dget_parent_lock(struct dentry *dentry,
37006+ unsigned int lsc)
1facf9fc 37007+{
062440b3
AM
37008+ struct dentry *parent;
37009+ struct inode *dir;
1facf9fc 37010+
062440b3 37011+ parent = dget_parent(dentry);
5527c038 37012+ dir = d_inode(parent);
062440b3
AM
37013+ inode_lock_nested(dir, lsc);
37014+#if 0 /* it should not happen */
37015+ spin_lock(&dentry->d_lock);
37016+ if (unlikely(dentry->d_parent != parent)) {
37017+ spin_unlock(&dentry->d_lock);
37018+ inode_unlock(dir);
37019+ dput(parent);
37020+ parent = NULL;
1facf9fc 37021+ goto out;
37022+ }
062440b3 37023+ spin_unlock(&dentry->d_lock);
1facf9fc 37024+
4f0767ce 37025+out:
062440b3
AM
37026+#endif
37027+ return parent;
1facf9fc 37028+}
37029+
062440b3 37030+static void au_xino_lock_dir(struct super_block *sb, struct path *xipath,
1facf9fc 37031+ struct au_xino_lock_dir *ldir)
37032+{
acd2b654 37033+ aufs_bindex_t bindex;
1facf9fc 37034+
37035+ ldir->hdir = NULL;
acd2b654 37036+ bindex = au_xi_root(sb, xipath->dentry);
1facf9fc 37037+ if (bindex >= 0) {
062440b3 37038+ /* rw branch root */
5527c038 37039+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 37040+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 37041+ } else {
062440b3
AM
37042+ /* other */
37043+ ldir->parent = au_dget_parent_lock(xipath->dentry,
37044+ AuLsc_I_PARENT);
febd17d6 37045+ ldir->dir = d_inode(ldir->parent);
1facf9fc 37046+ }
37047+}
37048+
37049+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
37050+{
37051+ if (ldir->hdir)
5afbbe0d 37052+ au_hn_inode_unlock(ldir->hdir);
1facf9fc 37053+ else {
febd17d6 37054+ inode_unlock(ldir->dir);
1facf9fc 37055+ dput(ldir->parent);
37056+ }
37057+}
37058+
37059+/* ---------------------------------------------------------------------- */
37060+
062440b3
AM
37061+/*
37062+ * create and set a new xino file
37063+ */
83b672a5
AM
37064+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
37065+ int wbrtop)
062440b3
AM
37066+{
37067+ struct file *file;
37068+ struct dentry *h_parent, *d;
37069+ struct inode *h_dir, *inode;
37070+ int err;
83b672a5 37071+ static DEFINE_MUTEX(mtx);
062440b3
AM
37072+
37073+ /*
37074+ * at mount-time, and the xino file is the default path,
37075+ * hnotify is disabled so we have no notify events to ignore.
37076+ * when a user specified the xino, we cannot get au_hdir to be ignored.
37077+ */
83b672a5
AM
37078+ if (!wbrtop)
37079+ mutex_lock(&mtx);
062440b3
AM
37080+ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
37081+ /* | __FMODE_NONOTIFY */,
cd7a4cd9 37082+ 0666);
062440b3 37083+ if (IS_ERR(file)) {
83b672a5
AM
37084+ if (!wbrtop)
37085+ mutex_unlock(&mtx);
062440b3
AM
37086+ if (!silent)
37087+ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file));
37088+ return file;
37089+ }
37090+
37091+ /* keep file count */
37092+ err = 0;
37093+ d = file->f_path.dentry;
37094+ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT);
83b672a5
AM
37095+ if (!wbrtop)
37096+ mutex_unlock(&mtx);
062440b3
AM
37097+ /* mnt_want_write() is unnecessary here */
37098+ h_dir = d_inode(h_parent);
37099+ inode = file_inode(file);
37100+ /* no delegation since it is just created */
37101+ if (inode->i_nlink)
37102+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL,
37103+ /*force*/0);
37104+ inode_unlock(h_dir);
37105+ dput(h_parent);
37106+ if (unlikely(err)) {
37107+ if (!silent)
37108+ pr_err("unlink %s(%d)\n", fpath, err);
37109+ goto out;
37110+ }
37111+
37112+ err = -EINVAL;
37113+ if (unlikely(sb == d->d_sb)) {
37114+ if (!silent)
37115+ pr_err("%s must be outside\n", fpath);
37116+ goto out;
37117+ }
37118+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
37119+ if (!silent)
37120+ pr_err("xino doesn't support %s(%s)\n",
37121+ fpath, au_sbtype(d->d_sb));
37122+ goto out;
37123+ }
37124+ return file; /* success */
37125+
37126+out:
37127+ fput(file);
37128+ file = ERR_PTR(err);
37129+ return file;
37130+}
37131+
37132+/*
37133+ * create a new xinofile at the same place/path as @base.
37134+ */
37135+struct file *au_xino_create2(struct super_block *sb, struct path *base,
37136+ struct file *copy_src)
37137+{
37138+ struct file *file;
37139+ struct dentry *dentry, *parent;
37140+ struct inode *dir, *delegated;
37141+ struct qstr *name;
37142+ struct path path;
37143+ int err, do_unlock;
37144+ struct au_xino_lock_dir ldir;
37145+
37146+ do_unlock = 1;
37147+ au_xino_lock_dir(sb, base, &ldir);
37148+ dentry = base->dentry;
37149+ parent = dentry->d_parent; /* dir inode is locked */
37150+ dir = d_inode(parent);
37151+ IMustLock(dir);
37152+
37153+ name = &dentry->d_name;
37154+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
37155+ if (IS_ERR(path.dentry)) {
37156+ file = (void *)path.dentry;
37157+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry));
37158+ goto out;
37159+ }
37160+
37161+ /* no need to mnt_want_write() since we call dentry_open() later */
cd7a4cd9 37162+ err = vfs_create(dir, path.dentry, 0666, NULL);
062440b3
AM
37163+ if (unlikely(err)) {
37164+ file = ERR_PTR(err);
37165+ pr_err("%pd create err %d\n", dentry, err);
37166+ goto out_dput;
37167+ }
37168+
37169+ path.mnt = base->mnt;
37170+ file = vfsub_dentry_open(&path,
37171+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
37172+ /* | __FMODE_NONOTIFY */);
37173+ if (IS_ERR(file)) {
37174+ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file));
37175+ goto out_dput;
37176+ }
37177+
37178+ delegated = NULL;
37179+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0);
37180+ au_xino_unlock_dir(&ldir);
37181+ do_unlock = 0;
37182+ if (unlikely(err == -EWOULDBLOCK)) {
37183+ pr_warn("cannot retry for NFSv4 delegation"
37184+ " for an internal unlink\n");
37185+ iput(delegated);
37186+ }
37187+ if (unlikely(err)) {
37188+ pr_err("%pd unlink err %d\n", dentry, err);
37189+ goto out_fput;
37190+ }
37191+
37192+ if (copy_src) {
37193+ /* no one can touch copy_src xino */
37194+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src));
37195+ if (unlikely(err)) {
37196+ pr_err("%pd copy err %d\n", dentry, err);
37197+ goto out_fput;
37198+ }
37199+ }
37200+ goto out_dput; /* success */
1facf9fc 37201+
062440b3
AM
37202+out_fput:
37203+ fput(file);
37204+ file = ERR_PTR(err);
37205+out_dput:
37206+ dput(path.dentry);
37207+out:
37208+ if (do_unlock)
37209+ au_xino_unlock_dir(&ldir);
37210+ return file;
37211+}
37212+
acd2b654
AM
37213+struct file *au_xino_file1(struct au_xino *xi)
37214+{
37215+ struct file *file;
37216+ unsigned int u, nfile;
37217+
37218+ file = NULL;
37219+ nfile = xi->xi_nfile;
37220+ for (u = 0; u < nfile; u++) {
37221+ file = xi->xi_file[u];
37222+ if (file)
37223+ break;
37224+ }
37225+
37226+ return file;
37227+}
37228+
37229+static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file)
37230+{
37231+ int err;
37232+ struct file *f;
37233+ void *p;
37234+
37235+ if (file)
37236+ get_file(file);
37237+
37238+ err = 0;
37239+ f = NULL;
37240+ if (idx < xi->xi_nfile) {
37241+ f = xi->xi_file[idx];
37242+ if (f)
37243+ fput(f);
37244+ } else {
37245+ p = au_kzrealloc(xi->xi_file,
37246+ sizeof(*xi->xi_file) * xi->xi_nfile,
37247+ sizeof(*xi->xi_file) * (idx + 1),
37248+ GFP_NOFS, /*may_shrink*/0);
37249+ if (p) {
37250+ MtxMustLock(&xi->xi_mtx);
37251+ xi->xi_file = p;
37252+ xi->xi_nfile = idx + 1;
37253+ } else {
37254+ err = -ENOMEM;
37255+ if (file)
37256+ fput(file);
37257+ goto out;
37258+ }
37259+ }
37260+ xi->xi_file[idx] = file;
37261+
37262+out:
37263+ return err;
37264+}
37265+
37266+/*
37267+ * if @xinew->xi is not set, then create new xigen file.
37268+ */
37269+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew)
37270+{
37271+ struct file *file;
37272+ int err;
37273+
37274+ SiMustAnyLock(sb);
37275+
37276+ file = au_xino_create2(sb, xinew->base, xinew->copy_src);
37277+ if (IS_ERR(file)) {
37278+ err = PTR_ERR(file);
37279+ pr_err("%s[%d], err %d\n",
37280+ xinew->xi ? "xino" : "xigen",
37281+ xinew->idx, err);
37282+ goto out;
37283+ }
37284+
37285+ if (xinew->xi)
37286+ err = au_xino_file_set(xinew->xi, xinew->idx, file);
37287+ else {
37288+ BUG();
37289+ /* todo: make xigen file an array */
37290+ /* err = au_xigen_file_set(sb, xinew->idx, file); */
37291+ }
37292+ fput(file);
37293+ if (unlikely(err))
37294+ file = ERR_PTR(err);
37295+
37296+out:
37297+ return file;
37298+}
37299+
062440b3
AM
37300+/* ---------------------------------------------------------------------- */
37301+
37302+/*
37303+ * truncate xino files
37304+ */
acd2b654
AM
37305+static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex,
37306+ int idx, struct kstatfs *st)
1facf9fc 37307+{
37308+ int err;
392086de 37309+ blkcnt_t blocks;
acd2b654
AM
37310+ struct file *file, *new_xino;
37311+ struct au_xi_new xinew = {
37312+ .idx = idx
37313+ };
37314+
37315+ err = 0;
37316+ xinew.xi = au_sbr(sb, bindex)->br_xino;
37317+ file = au_xino_file(xinew.xi, idx);
37318+ if (!file)
37319+ goto out;
37320+
37321+ xinew.base = &file->f_path;
37322+ err = vfs_statfs(xinew.base, st);
37323+ if (unlikely(err)) {
37324+ AuErr1("statfs err %d, ignored\n", err);
37325+ err = 0;
37326+ goto out;
37327+ }
37328+
37329+ blocks = file_inode(file)->i_blocks;
37330+ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37331+ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks);
37332+
37333+ xinew.copy_src = file;
37334+ new_xino = au_xi_new(sb, &xinew);
37335+ if (IS_ERR(new_xino)) {
37336+ err = PTR_ERR(new_xino);
37337+ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err);
37338+ goto out;
37339+ }
37340+
37341+ err = vfs_statfs(&new_xino->f_path, st);
37342+ if (!err)
37343+ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37344+ bindex, idx, (u64)file_inode(new_xino)->i_blocks,
37345+ st->f_bfree, st->f_blocks);
37346+ else {
37347+ AuErr1("statfs err %d, ignored\n", err);
37348+ err = 0;
37349+ }
37350+
37351+out:
37352+ return err;
37353+}
37354+
37355+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin)
37356+{
37357+ int err, i;
37358+ unsigned long jiffy;
062440b3 37359+ aufs_bindex_t bbot;
392086de 37360+ struct kstatfs *st;
1facf9fc 37361+ struct au_branch *br;
acd2b654 37362+ struct au_xino *xi;
1facf9fc 37363+
392086de 37364+ err = -ENOMEM;
be52b249 37365+ st = kmalloc(sizeof(*st), GFP_NOFS);
392086de
AM
37366+ if (unlikely(!st))
37367+ goto out;
37368+
1facf9fc 37369+ err = -EINVAL;
5afbbe0d
AM
37370+ bbot = au_sbbot(sb);
37371+ if (unlikely(bindex < 0 || bbot < bindex))
392086de 37372+ goto out_st;
392086de 37373+
1facf9fc 37374+ err = 0;
acd2b654
AM
37375+ jiffy = jiffies;
37376+ br = au_sbr(sb, bindex);
37377+ xi = br->br_xino;
37378+ for (i = idx_begin; !err && i < xi->xi_nfile; i++)
37379+ err = au_xino_do_trunc(sb, bindex, i, st);
37380+ if (!err)
37381+ au_sbi(sb)->si_xino_jiffy = jiffy;
392086de
AM
37382+
37383+out_st:
9f237c51 37384+ au_kfree_rcu(st);
4f0767ce 37385+out:
1facf9fc 37386+ return err;
37387+}
37388+
37389+struct xino_do_trunc_args {
37390+ struct super_block *sb;
37391+ struct au_branch *br;
acd2b654 37392+ int idx;
1facf9fc 37393+};
37394+
37395+static void xino_do_trunc(void *_args)
37396+{
37397+ struct xino_do_trunc_args *args = _args;
37398+ struct super_block *sb;
37399+ struct au_branch *br;
37400+ struct inode *dir;
acd2b654 37401+ int err, idx;
1facf9fc 37402+ aufs_bindex_t bindex;
37403+
37404+ err = 0;
37405+ sb = args->sb;
5527c038 37406+ dir = d_inode(sb->s_root);
1facf9fc 37407+ br = args->br;
acd2b654 37408+ idx = args->idx;
1facf9fc 37409+
37410+ si_noflush_write_lock(sb);
37411+ ii_read_lock_parent(dir);
37412+ bindex = au_br_index(sb, br->br_id);
acd2b654 37413+ err = au_xino_trunc(sb, bindex, idx);
1facf9fc 37414+ ii_read_unlock(dir);
37415+ if (unlikely(err))
392086de 37416+ pr_warn("err b%d, (%d)\n", bindex, err);
062440b3 37417+ atomic_dec(&br->br_xino->xi_truncating);
acd2b654 37418+ au_lcnt_dec(&br->br_count);
1facf9fc 37419+ si_write_unlock(sb);
027c5e7a 37420+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 37421+ au_kfree_rcu(args);
1facf9fc 37422+}
37423+
acd2b654
AM
37424+/*
37425+ * returns the index in the xi_file array whose corresponding file is necessary
37426+ * to truncate, or -1 which means no need to truncate.
37427+ */
392086de
AM
37428+static int xino_trunc_test(struct super_block *sb, struct au_branch *br)
37429+{
37430+ int err;
acd2b654 37431+ unsigned int u;
392086de
AM
37432+ struct kstatfs st;
37433+ struct au_sbinfo *sbinfo;
acd2b654 37434+ struct au_xino *xi;
062440b3 37435+ struct file *file;
392086de
AM
37436+
37437+ /* todo: si_xino_expire and the ratio should be customizable */
37438+ sbinfo = au_sbi(sb);
37439+ if (time_before(jiffies,
37440+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire))
acd2b654 37441+ return -1;
392086de
AM
37442+
37443+ /* truncation border */
acd2b654
AM
37444+ xi = br->br_xino;
37445+ for (u = 0; u < xi->xi_nfile; u++) {
37446+ file = au_xino_file(xi, u);
37447+ if (!file)
37448+ continue;
37449+
37450+ err = vfs_statfs(&file->f_path, &st);
37451+ if (unlikely(err)) {
37452+ AuErr1("statfs err %d, ignored\n", err);
37453+ return -1;
37454+ }
37455+ if (div64_u64(st.f_bfree * 100, st.f_blocks)
37456+ >= AUFS_XINO_DEF_TRUNC)
37457+ return u;
392086de 37458+ }
392086de 37459+
acd2b654 37460+ return -1;
392086de
AM
37461+}
37462+
1facf9fc 37463+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
37464+{
acd2b654 37465+ int idx;
1facf9fc 37466+ struct xino_do_trunc_args *args;
37467+ int wkq_err;
37468+
acd2b654
AM
37469+ idx = xino_trunc_test(sb, br);
37470+ if (idx < 0)
1facf9fc 37471+ return;
37472+
062440b3 37473+ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1)
1facf9fc 37474+ goto out;
37475+
37476+ /* lock and kfree() will be called in trunc_xino() */
37477+ args = kmalloc(sizeof(*args), GFP_NOFS);
37478+ if (unlikely(!args)) {
37479+ AuErr1("no memory\n");
f0c0a007 37480+ goto out;
1facf9fc 37481+ }
37482+
acd2b654 37483+ au_lcnt_inc(&br->br_count);
1facf9fc 37484+ args->sb = sb;
37485+ args->br = br;
acd2b654 37486+ args->idx = idx;
53392da6 37487+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 37488+ if (!wkq_err)
37489+ return; /* success */
37490+
4a4d8108 37491+ pr_err("wkq %d\n", wkq_err);
acd2b654 37492+ au_lcnt_dec(&br->br_count);
9f237c51 37493+ au_kfree_rcu(args);
1facf9fc 37494+
4f0767ce 37495+out:
062440b3 37496+ atomic_dec(&br->br_xino->xi_truncating);
1facf9fc 37497+}
37498+
37499+/* ---------------------------------------------------------------------- */
37500+
acd2b654
AM
37501+struct au_xi_calc {
37502+ int idx;
37503+ loff_t pos;
37504+};
37505+
37506+static void au_xi_calc(struct super_block *sb, ino_t h_ino,
37507+ struct au_xi_calc *calc)
37508+{
37509+ loff_t maxent;
37510+
37511+ maxent = au_xi_maxent(sb);
37512+ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos);
37513+ calc->pos *= sizeof(ino_t);
37514+}
37515+
37516+static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br,
37517+ struct au_xi_calc *calc)
37518+{
37519+ int err;
37520+ struct file *file;
37521+ struct au_xino *xi = br->br_xino;
37522+ struct au_xi_new xinew = {
37523+ .xi = xi
37524+ };
37525+
37526+ SiMustAnyLock(sb);
37527+
37528+ err = 0;
37529+ if (!xi)
37530+ goto out;
37531+
37532+ mutex_lock(&xi->xi_mtx);
37533+ file = au_xino_file(xi, calc->idx);
37534+ if (file)
37535+ goto out_mtx;
37536+
37537+ file = au_xino_file(xi, /*idx*/-1);
37538+ AuDebugOn(!file);
37539+ xinew.idx = calc->idx;
37540+ xinew.base = &file->f_path;
37541+ /* xinew.copy_src = NULL; */
37542+ file = au_xi_new(sb, &xinew);
37543+ if (IS_ERR(file))
37544+ err = PTR_ERR(file);
37545+
37546+out_mtx:
37547+ mutex_unlock(&xi->xi_mtx);
37548+out:
37549+ return err;
37550+}
37551+
37552+struct au_xino_do_new_async_args {
37553+ struct super_block *sb;
37554+ struct au_branch *br;
37555+ struct au_xi_calc calc;
37556+ ino_t ino;
37557+};
37558+
9f237c51
AM
37559+struct au_xi_writing {
37560+ struct hlist_bl_node node;
37561+ ino_t h_ino, ino;
37562+};
37563+
acd2b654
AM
37564+static int au_xino_do_write(vfs_writef_t write, struct file *file,
37565+ struct au_xi_calc *calc, ino_t ino);
37566+
37567+static void au_xino_call_do_new_async(void *args)
37568+{
37569+ struct au_xino_do_new_async_args *a = args;
37570+ struct au_branch *br;
37571+ struct super_block *sb;
37572+ struct au_sbinfo *sbi;
37573+ struct inode *root;
37574+ struct file *file;
9f237c51
AM
37575+ struct au_xi_writing *del, *p;
37576+ struct hlist_bl_head *hbl;
37577+ struct hlist_bl_node *pos;
acd2b654
AM
37578+ int err;
37579+
37580+ br = a->br;
37581+ sb = a->sb;
37582+ sbi = au_sbi(sb);
37583+ si_noflush_read_lock(sb);
37584+ root = d_inode(sb->s_root);
37585+ ii_read_lock_child(root);
37586+ err = au_xino_do_new_async(sb, br, &a->calc);
9f237c51
AM
37587+ if (unlikely(err)) {
37588+ AuIOErr("err %d\n", err);
37589+ goto out;
37590+ }
37591+
37592+ file = au_xino_file(br->br_xino, a->calc.idx);
37593+ AuDebugOn(!file);
37594+ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino);
37595+ if (unlikely(err)) {
acd2b654 37596+ AuIOErr("err %d\n", err);
9f237c51
AM
37597+ goto out;
37598+ }
37599+
37600+ del = NULL;
37601+ hbl = &br->br_xino->xi_writing;
37602+ hlist_bl_lock(hbl);
37603+ au_hbl_for_each(pos, hbl) {
37604+ p = container_of(pos, struct au_xi_writing, node);
37605+ if (p->ino == a->ino) {
37606+ del = p;
37607+ hlist_bl_del(&p->node);
37608+ break;
37609+ }
37610+ }
37611+ hlist_bl_unlock(hbl);
37612+ au_kfree_rcu(del);
37613+
37614+out:
acd2b654
AM
37615+ au_lcnt_dec(&br->br_count);
37616+ ii_read_unlock(root);
37617+ si_read_unlock(sb);
37618+ au_nwt_done(&sbi->si_nowait);
9f237c51 37619+ au_kfree_rcu(a);
acd2b654
AM
37620+}
37621+
37622+/*
37623+ * create a new xino file asynchronously
37624+ */
37625+static int au_xino_new_async(struct super_block *sb, struct au_branch *br,
37626+ struct au_xi_calc *calc, ino_t ino)
37627+{
37628+ int err;
37629+ struct au_xino_do_new_async_args *arg;
37630+
37631+ err = -ENOMEM;
37632+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
37633+ if (unlikely(!arg))
37634+ goto out;
37635+
37636+ arg->sb = sb;
37637+ arg->br = br;
37638+ arg->calc = *calc;
37639+ arg->ino = ino;
37640+ au_lcnt_inc(&br->br_count);
37641+ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST);
37642+ if (unlikely(err)) {
37643+ pr_err("wkq %d\n", err);
37644+ au_lcnt_dec(&br->br_count);
9f237c51 37645+ au_kfree_rcu(arg);
acd2b654
AM
37646+ }
37647+
37648+out:
37649+ return err;
37650+}
37651+
062440b3
AM
37652+/*
37653+ * read @ino from xinofile for the specified branch{@sb, @bindex}
37654+ * at the position of @h_ino.
37655+ */
37656+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37657+ ino_t *ino)
37658+{
37659+ int err;
37660+ ssize_t sz;
acd2b654 37661+ struct au_xi_calc calc;
062440b3 37662+ struct au_sbinfo *sbinfo;
acd2b654 37663+ struct file *file;
9f237c51
AM
37664+ struct au_xino *xi;
37665+ struct hlist_bl_head *hbl;
37666+ struct hlist_bl_node *pos;
37667+ struct au_xi_writing *p;
062440b3
AM
37668+
37669+ *ino = 0;
37670+ if (!au_opt_test(au_mntflags(sb), XINO))
37671+ return 0; /* no xino */
37672+
37673+ err = 0;
acd2b654 37674+ au_xi_calc(sb, h_ino, &calc);
9f237c51
AM
37675+ xi = au_sbr(sb, bindex)->br_xino;
37676+ file = au_xino_file(xi, calc.idx);
37677+ if (!file) {
37678+ hbl = &xi->xi_writing;
37679+ hlist_bl_lock(hbl);
37680+ au_hbl_for_each(pos, hbl) {
37681+ p = container_of(pos, struct au_xi_writing, node);
37682+ if (p->h_ino == h_ino) {
37683+ AuDbg("hi%llu, i%llu, found\n",
37684+ (u64)p->h_ino, (u64)p->ino);
37685+ *ino = p->ino;
37686+ break;
37687+ }
37688+ }
37689+ hlist_bl_unlock(hbl);
37690+ return 0;
37691+ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino))
37692+ return 0; /* no xino */
062440b3 37693+
acd2b654
AM
37694+ sbinfo = au_sbi(sb);
37695+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos);
062440b3
AM
37696+ if (sz == sizeof(*ino))
37697+ return 0; /* success */
37698+
37699+ err = sz;
37700+ if (unlikely(sz >= 0)) {
37701+ err = -EIO;
37702+ AuIOErr("xino read error (%zd)\n", sz);
37703+ }
062440b3
AM
37704+ return err;
37705+}
37706+
5527c038 37707+static int au_xino_do_write(vfs_writef_t write, struct file *file,
acd2b654 37708+ struct au_xi_calc *calc, ino_t ino)
1facf9fc 37709+{
1facf9fc 37710+ ssize_t sz;
37711+
acd2b654 37712+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos);
1facf9fc 37713+ if (sz == sizeof(ino))
37714+ return 0; /* success */
37715+
37716+ AuIOErr("write failed (%zd)\n", sz);
37717+ return -EIO;
37718+}
37719+
37720+/*
37721+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
37722+ * at the position of @h_ino.
37723+ * even if @ino is zero, it is written to the xinofile and means no entry.
37724+ * if the size of the xino file on a specific filesystem exceeds the watermark,
37725+ * try truncating it.
37726+ */
37727+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37728+ ino_t ino)
37729+{
37730+ int err;
37731+ unsigned int mnt_flags;
acd2b654
AM
37732+ struct au_xi_calc calc;
37733+ struct file *file;
1facf9fc 37734+ struct au_branch *br;
acd2b654 37735+ struct au_xino *xi;
9f237c51 37736+ struct au_xi_writing *p;
1facf9fc 37737+
dece6358 37738+ SiMustAnyLock(sb);
1facf9fc 37739+
37740+ mnt_flags = au_mntflags(sb);
37741+ if (!au_opt_test(mnt_flags, XINO))
37742+ return 0;
37743+
acd2b654 37744+ au_xi_calc(sb, h_ino, &calc);
1facf9fc 37745+ br = au_sbr(sb, bindex);
acd2b654
AM
37746+ xi = br->br_xino;
37747+ file = au_xino_file(xi, calc.idx);
37748+ if (!file) {
9f237c51
AM
37749+ /* store the inum pair into the list */
37750+ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL);
37751+ p->h_ino = h_ino;
37752+ p->ino = ino;
37753+ au_hbl_add(&p->node, &xi->xi_writing);
37754+
acd2b654
AM
37755+ /* create and write a new xino file asynchronously */
37756+ err = au_xino_new_async(sb, br, &calc, ino);
37757+ if (!err)
37758+ return 0; /* success */
37759+ goto out;
37760+ }
37761+
37762+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino);
1facf9fc 37763+ if (!err) {
acd2b654 37764+ br = au_sbr(sb, bindex);
1facf9fc 37765+ if (au_opt_test(mnt_flags, TRUNC_XINO)
86dc4139 37766+ && au_test_fs_trunc_xino(au_br_sb(br)))
1facf9fc 37767+ xino_try_trunc(sb, br);
37768+ return 0; /* success */
37769+ }
37770+
acd2b654 37771+out:
1facf9fc 37772+ AuIOErr("write failed (%d)\n", err);
37773+ return -EIO;
37774+}
37775+
062440b3
AM
37776+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf,
37777+ size_t size, loff_t *pos);
1facf9fc 37778+
062440b3
AM
37779+/* todo: unnecessary to support mmap_sem since kernel-space? */
37780+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size,
37781+ loff_t *pos)
37782+{
37783+ ssize_t err;
37784+ mm_segment_t oldfs;
37785+ union {
37786+ void *k;
37787+ char __user *u;
37788+ } buf;
37789+ int i;
37790+ const int prevent_endless = 10;
1facf9fc 37791+
062440b3
AM
37792+ i = 0;
37793+ buf.k = kbuf;
37794+ oldfs = get_fs();
37795+ set_fs(KERNEL_DS);
37796+ do {
37797+ err = func(file, buf.u, size, pos);
37798+ if (err == -EINTR
37799+ && !au_wkq_test()
37800+ && fatal_signal_pending(current)) {
37801+ set_fs(oldfs);
37802+ err = xino_fread_wkq(func, file, kbuf, size, pos);
37803+ BUG_ON(err == -EINTR);
37804+ oldfs = get_fs();
37805+ set_fs(KERNEL_DS);
37806+ }
37807+ } while (i++ < prevent_endless
37808+ && (err == -EAGAIN || err == -EINTR));
37809+ set_fs(oldfs);
37810+
37811+#if 0 /* reserved for future use */
37812+ if (err > 0)
37813+ fsnotify_access(file->f_path.dentry);
37814+#endif
37815+
37816+ return err;
37817+}
37818+
37819+struct xino_fread_args {
37820+ ssize_t *errp;
37821+ vfs_readf_t func;
37822+ struct file *file;
37823+ void *buf;
37824+ size_t size;
37825+ loff_t *pos;
37826+};
37827+
37828+static void call_xino_fread(void *args)
37829+{
37830+ struct xino_fread_args *a = args;
37831+ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos);
37832+}
37833+
37834+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf,
37835+ size_t size, loff_t *pos)
37836+{
37837+ ssize_t err;
37838+ int wkq_err;
37839+ struct xino_fread_args args = {
37840+ .errp = &err,
37841+ .func = func,
37842+ .file = file,
37843+ .buf = buf,
37844+ .size = size,
37845+ .pos = pos
37846+ };
37847+
37848+ wkq_err = au_wkq_wait(call_xino_fread, &args);
37849+ if (unlikely(wkq_err))
37850+ err = wkq_err;
37851+
37852+ return err;
37853+}
37854+
37855+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
37856+ size_t size, loff_t *pos);
37857+
37858+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf,
37859+ size_t size, loff_t *pos)
37860+{
37861+ ssize_t err;
37862+ mm_segment_t oldfs;
37863+ union {
37864+ void *k;
37865+ const char __user *u;
37866+ } buf;
37867+ int i;
37868+ const int prevent_endless = 10;
37869+
37870+ i = 0;
37871+ buf.k = kbuf;
37872+ oldfs = get_fs();
37873+ set_fs(KERNEL_DS);
37874+ do {
37875+ err = func(file, buf.u, size, pos);
37876+ if (err == -EINTR
37877+ && !au_wkq_test()
37878+ && fatal_signal_pending(current)) {
37879+ set_fs(oldfs);
37880+ err = xino_fwrite_wkq(func, file, kbuf, size, pos);
37881+ BUG_ON(err == -EINTR);
37882+ oldfs = get_fs();
37883+ set_fs(KERNEL_DS);
37884+ }
37885+ } while (i++ < prevent_endless
37886+ && (err == -EAGAIN || err == -EINTR));
37887+ set_fs(oldfs);
37888+
37889+#if 0 /* reserved for future use */
37890+ if (err > 0)
37891+ fsnotify_modify(file->f_path.dentry);
37892+#endif
37893+
37894+ return err;
37895+}
37896+
37897+struct do_xino_fwrite_args {
37898+ ssize_t *errp;
37899+ vfs_writef_t func;
37900+ struct file *file;
37901+ void *buf;
37902+ size_t size;
37903+ loff_t *pos;
37904+};
37905+
37906+static void call_do_xino_fwrite(void *args)
37907+{
37908+ struct do_xino_fwrite_args *a = args;
37909+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
37910+}
37911+
37912+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
37913+ size_t size, loff_t *pos)
37914+{
37915+ ssize_t err;
37916+ int wkq_err;
37917+ struct do_xino_fwrite_args args = {
37918+ .errp = &err,
37919+ .func = func,
37920+ .file = file,
37921+ .buf = buf,
37922+ .size = size,
37923+ .pos = pos
37924+ };
37925+
37926+ /*
37927+ * it breaks RLIMIT_FSIZE and normal user's limit,
37928+ * users should care about quota and real 'filesystem full.'
37929+ */
37930+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
37931+ if (unlikely(wkq_err))
37932+ err = wkq_err;
37933+
37934+ return err;
37935+}
37936+
37937+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
37938+ size_t size, loff_t *pos)
37939+{
37940+ ssize_t err;
37941+
37942+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
37943+ lockdep_off();
37944+ err = do_xino_fwrite(func, file, buf, size, pos);
37945+ lockdep_on();
37946+ } else {
37947+ lockdep_off();
37948+ err = xino_fwrite_wkq(func, file, buf, size, pos);
37949+ lockdep_on();
37950+ }
37951+
37952+ return err;
37953+}
37954+
37955+/* ---------------------------------------------------------------------- */
37956+
37957+/*
37958+ * inode number bitmap
37959+ */
1facf9fc 37960+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
37961+static ino_t xib_calc_ino(unsigned long pindex, int bit)
37962+{
37963+ ino_t ino;
37964+
37965+ AuDebugOn(bit < 0 || page_bits <= bit);
37966+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
37967+ return ino;
37968+}
37969+
37970+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
37971+{
37972+ AuDebugOn(ino < AUFS_FIRST_INO);
37973+ ino -= AUFS_FIRST_INO;
37974+ *pindex = ino / page_bits;
37975+ *bit = ino % page_bits;
37976+}
37977+
37978+static int xib_pindex(struct super_block *sb, unsigned long pindex)
37979+{
37980+ int err;
37981+ loff_t pos;
37982+ ssize_t sz;
37983+ struct au_sbinfo *sbinfo;
37984+ struct file *xib;
37985+ unsigned long *p;
37986+
37987+ sbinfo = au_sbi(sb);
37988+ MtxMustLock(&sbinfo->si_xib_mtx);
37989+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
37990+ || !au_opt_test(sbinfo->si_mntflags, XINO));
37991+
37992+ if (pindex == sbinfo->si_xib_last_pindex)
37993+ return 0;
37994+
37995+ xib = sbinfo->si_xib;
37996+ p = sbinfo->si_xib_buf;
37997+ pos = sbinfo->si_xib_last_pindex;
37998+ pos *= PAGE_SIZE;
37999+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
38000+ if (unlikely(sz != PAGE_SIZE))
38001+ goto out;
38002+
38003+ pos = pindex;
38004+ pos *= PAGE_SIZE;
c06a8ce3 38005+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE)
1facf9fc 38006+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
38007+ else {
38008+ memset(p, 0, PAGE_SIZE);
38009+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
38010+ }
38011+ if (sz == PAGE_SIZE) {
38012+ sbinfo->si_xib_last_pindex = pindex;
38013+ return 0; /* success */
38014+ }
38015+
4f0767ce 38016+out:
b752ccd1
AM
38017+ AuIOErr1("write failed (%zd)\n", sz);
38018+ err = sz;
38019+ if (sz >= 0)
38020+ err = -EIO;
38021+ return err;
38022+}
38023+
b752ccd1
AM
38024+static void au_xib_clear_bit(struct inode *inode)
38025+{
38026+ int err, bit;
38027+ unsigned long pindex;
38028+ struct super_block *sb;
38029+ struct au_sbinfo *sbinfo;
38030+
38031+ AuDebugOn(inode->i_nlink);
38032+
38033+ sb = inode->i_sb;
38034+ xib_calc_bit(inode->i_ino, &pindex, &bit);
38035+ AuDebugOn(page_bits <= bit);
38036+ sbinfo = au_sbi(sb);
38037+ mutex_lock(&sbinfo->si_xib_mtx);
38038+ err = xib_pindex(sb, pindex);
38039+ if (!err) {
38040+ clear_bit(bit, sbinfo->si_xib_buf);
38041+ sbinfo->si_xib_next_bit = bit;
38042+ }
38043+ mutex_unlock(&sbinfo->si_xib_mtx);
38044+}
38045+
1facf9fc 38046+/* ---------------------------------------------------------------------- */
38047+
1facf9fc 38048+/*
062440b3 38049+ * truncate a xino bitmap file
1facf9fc 38050+ */
1facf9fc 38051+
38052+/* todo: slow */
38053+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
38054+{
38055+ int err, bit;
38056+ ssize_t sz;
38057+ unsigned long pindex;
38058+ loff_t pos, pend;
38059+ struct au_sbinfo *sbinfo;
5527c038 38060+ vfs_readf_t func;
1facf9fc 38061+ ino_t *ino;
38062+ unsigned long *p;
38063+
38064+ err = 0;
38065+ sbinfo = au_sbi(sb);
dece6358 38066+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 38067+ p = sbinfo->si_xib_buf;
38068+ func = sbinfo->si_xread;
c06a8ce3 38069+ pend = vfsub_f_size_read(file);
1facf9fc 38070+ pos = 0;
38071+ while (pos < pend) {
38072+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
38073+ err = sz;
38074+ if (unlikely(sz <= 0))
38075+ goto out;
38076+
38077+ err = 0;
38078+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
38079+ if (unlikely(*ino < AUFS_FIRST_INO))
38080+ continue;
38081+
38082+ xib_calc_bit(*ino, &pindex, &bit);
38083+ AuDebugOn(page_bits <= bit);
38084+ err = xib_pindex(sb, pindex);
38085+ if (!err)
38086+ set_bit(bit, p);
38087+ else
38088+ goto out;
38089+ }
38090+ }
38091+
4f0767ce 38092+out:
1facf9fc 38093+ return err;
38094+}
38095+
38096+static int xib_restore(struct super_block *sb)
38097+{
acd2b654
AM
38098+ int err, i;
38099+ unsigned int nfile;
5afbbe0d 38100+ aufs_bindex_t bindex, bbot;
1facf9fc 38101+ void *page;
062440b3 38102+ struct au_branch *br;
acd2b654
AM
38103+ struct au_xino *xi;
38104+ struct file *file;
1facf9fc 38105+
38106+ err = -ENOMEM;
38107+ page = (void *)__get_free_page(GFP_NOFS);
38108+ if (unlikely(!page))
38109+ goto out;
38110+
38111+ err = 0;
5afbbe0d
AM
38112+ bbot = au_sbbot(sb);
38113+ for (bindex = 0; !err && bindex <= bbot; bindex++)
062440b3
AM
38114+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) {
38115+ br = au_sbr(sb, bindex);
acd2b654
AM
38116+ xi = br->br_xino;
38117+ nfile = xi->xi_nfile;
38118+ for (i = 0; i < nfile; i++) {
38119+ file = au_xino_file(xi, i);
38120+ if (file)
38121+ err = do_xib_restore(sb, file, page);
38122+ }
062440b3
AM
38123+ } else
38124+ AuDbg("skip shared b%d\n", bindex);
1c60b727 38125+ free_page((unsigned long)page);
1facf9fc 38126+
4f0767ce 38127+out:
1facf9fc 38128+ return err;
38129+}
38130+
38131+int au_xib_trunc(struct super_block *sb)
38132+{
38133+ int err;
38134+ ssize_t sz;
38135+ loff_t pos;
1facf9fc 38136+ struct au_sbinfo *sbinfo;
38137+ unsigned long *p;
38138+ struct file *file;
38139+
dece6358
AM
38140+ SiMustWriteLock(sb);
38141+
1facf9fc 38142+ err = 0;
38143+ sbinfo = au_sbi(sb);
38144+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
38145+ goto out;
38146+
38147+ file = sbinfo->si_xib;
c06a8ce3 38148+ if (vfsub_f_size_read(file) <= PAGE_SIZE)
1facf9fc 38149+ goto out;
38150+
062440b3 38151+ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL);
1facf9fc 38152+ err = PTR_ERR(file);
38153+ if (IS_ERR(file))
38154+ goto out;
38155+ fput(sbinfo->si_xib);
38156+ sbinfo->si_xib = file;
38157+
38158+ p = sbinfo->si_xib_buf;
38159+ memset(p, 0, PAGE_SIZE);
38160+ pos = 0;
38161+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
38162+ if (unlikely(sz != PAGE_SIZE)) {
38163+ err = sz;
38164+ AuIOErr("err %d\n", err);
38165+ if (sz >= 0)
38166+ err = -EIO;
38167+ goto out;
38168+ }
38169+
38170+ mutex_lock(&sbinfo->si_xib_mtx);
38171+ /* mnt_want_write() is unnecessary here */
38172+ err = xib_restore(sb);
38173+ mutex_unlock(&sbinfo->si_xib_mtx);
38174+
38175+out:
38176+ return err;
38177+}
38178+
38179+/* ---------------------------------------------------------------------- */
38180+
acd2b654 38181+struct au_xino *au_xino_alloc(unsigned int nfile)
062440b3
AM
38182+{
38183+ struct au_xino *xi;
38184+
38185+ xi = kzalloc(sizeof(*xi), GFP_NOFS);
38186+ if (unlikely(!xi))
38187+ goto out;
acd2b654
AM
38188+ xi->xi_nfile = nfile;
38189+ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS);
38190+ if (unlikely(!xi->xi_file))
38191+ goto out_free;
062440b3
AM
38192+
38193+ xi->xi_nondir.total = 8; /* initial size */
38194+ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t),
38195+ GFP_NOFS);
38196+ if (unlikely(!xi->xi_nondir.array))
acd2b654 38197+ goto out_file;
062440b3
AM
38198+
38199+ spin_lock_init(&xi->xi_nondir.spin);
38200+ init_waitqueue_head(&xi->xi_nondir.wqh);
acd2b654 38201+ mutex_init(&xi->xi_mtx);
9f237c51 38202+ INIT_HLIST_BL_HEAD(&xi->xi_writing);
062440b3
AM
38203+ atomic_set(&xi->xi_truncating, 0);
38204+ kref_init(&xi->xi_kref);
38205+ goto out; /* success */
38206+
acd2b654 38207+out_file:
9f237c51 38208+ au_kfree_try_rcu(xi->xi_file);
062440b3 38209+out_free:
9f237c51 38210+ au_kfree_rcu(xi);
062440b3
AM
38211+ xi = NULL;
38212+out:
38213+ return xi;
38214+}
38215+
acd2b654 38216+static int au_xino_init(struct au_branch *br, int idx, struct file *file)
062440b3
AM
38217+{
38218+ int err;
38219+ struct au_xino *xi;
38220+
38221+ err = 0;
acd2b654 38222+ xi = au_xino_alloc(idx + 1);
062440b3
AM
38223+ if (unlikely(!xi)) {
38224+ err = -ENOMEM;
38225+ goto out;
38226+ }
38227+
acd2b654
AM
38228+ if (file)
38229+ get_file(file);
38230+ xi->xi_file[idx] = file;
062440b3
AM
38231+ AuDebugOn(br->br_xino);
38232+ br->br_xino = xi;
38233+
38234+out:
38235+ return err;
38236+}
38237+
38238+static void au_xino_release(struct kref *kref)
38239+{
38240+ struct au_xino *xi;
38241+ int i;
9f237c51
AM
38242+ unsigned long ul;
38243+ struct hlist_bl_head *hbl;
38244+ struct hlist_bl_node *pos, *n;
38245+ struct au_xi_writing *p;
062440b3
AM
38246+
38247+ xi = container_of(kref, struct au_xino, xi_kref);
acd2b654
AM
38248+ for (i = 0; i < xi->xi_nfile; i++)
38249+ if (xi->xi_file[i])
38250+ fput(xi->xi_file[i]);
062440b3
AM
38251+ for (i = xi->xi_nondir.total - 1; i >= 0; i--)
38252+ AuDebugOn(xi->xi_nondir.array[i]);
acd2b654 38253+ mutex_destroy(&xi->xi_mtx);
9f237c51
AM
38254+ hbl = &xi->xi_writing;
38255+ ul = au_hbl_count(hbl);
38256+ if (unlikely(ul)) {
38257+ pr_warn("xi_writing %lu\n", ul);
38258+ hlist_bl_lock(hbl);
38259+ hlist_bl_for_each_entry_safe (p, pos, n, hbl, node) {
38260+ hlist_bl_del(&p->node);
38261+ au_kfree_rcu(p);
38262+ }
38263+ hlist_bl_unlock(hbl);
38264+ }
38265+ au_kfree_try_rcu(xi->xi_file);
38266+ au_kfree_try_rcu(xi->xi_nondir.array);
38267+ au_kfree_rcu(xi);
062440b3
AM
38268+}
38269+
38270+int au_xino_put(struct au_branch *br)
38271+{
38272+ int ret;
38273+ struct au_xino *xi;
38274+
38275+ ret = 0;
38276+ xi = br->br_xino;
38277+ if (xi) {
38278+ br->br_xino = NULL;
38279+ ret = kref_put(&xi->xi_kref, au_xino_release);
38280+ }
38281+
38282+ return ret;
38283+}
38284+
062440b3
AM
38285+/* ---------------------------------------------------------------------- */
38286+
1facf9fc 38287+/*
38288+ * xino mount option handlers
38289+ */
1facf9fc 38290+
38291+/* xino bitmap */
38292+static void xino_clear_xib(struct super_block *sb)
38293+{
38294+ struct au_sbinfo *sbinfo;
38295+
dece6358
AM
38296+ SiMustWriteLock(sb);
38297+
1facf9fc 38298+ sbinfo = au_sbi(sb);
062440b3 38299+ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */
1facf9fc 38300+ if (sbinfo->si_xib)
38301+ fput(sbinfo->si_xib);
38302+ sbinfo->si_xib = NULL;
f0c0a007 38303+ if (sbinfo->si_xib_buf)
1c60b727 38304+ free_page((unsigned long)sbinfo->si_xib_buf);
1facf9fc 38305+ sbinfo->si_xib_buf = NULL;
38306+}
38307+
062440b3 38308+static int au_xino_set_xib(struct super_block *sb, struct path *path)
1facf9fc 38309+{
38310+ int err;
38311+ loff_t pos;
38312+ struct au_sbinfo *sbinfo;
38313+ struct file *file;
acd2b654 38314+ struct super_block *xi_sb;
1facf9fc 38315+
dece6358
AM
38316+ SiMustWriteLock(sb);
38317+
1facf9fc 38318+ sbinfo = au_sbi(sb);
062440b3 38319+ file = au_xino_create2(sb, path, sbinfo->si_xib);
1facf9fc 38320+ err = PTR_ERR(file);
38321+ if (IS_ERR(file))
38322+ goto out;
38323+ if (sbinfo->si_xib)
38324+ fput(sbinfo->si_xib);
38325+ sbinfo->si_xib = file;
5527c038
JR
38326+ sbinfo->si_xread = vfs_readf(file);
38327+ sbinfo->si_xwrite = vfs_writef(file);
acd2b654
AM
38328+ xi_sb = file_inode(file)->i_sb;
38329+ sbinfo->si_ximaxent = xi_sb->s_maxbytes;
38330+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) {
38331+ err = -EIO;
38332+ pr_err("s_maxbytes(%llu) on %s is too small\n",
38333+ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb));
38334+ goto out_unset;
38335+ }
38336+ sbinfo->si_ximaxent /= sizeof(ino_t);
1facf9fc 38337+
38338+ err = -ENOMEM;
38339+ if (!sbinfo->si_xib_buf)
38340+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
38341+ if (unlikely(!sbinfo->si_xib_buf))
38342+ goto out_unset;
38343+
38344+ sbinfo->si_xib_last_pindex = 0;
38345+ sbinfo->si_xib_next_bit = 0;
c06a8ce3 38346+ if (vfsub_f_size_read(file) < PAGE_SIZE) {
1facf9fc 38347+ pos = 0;
38348+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
38349+ PAGE_SIZE, &pos);
38350+ if (unlikely(err != PAGE_SIZE))
38351+ goto out_free;
38352+ }
38353+ err = 0;
38354+ goto out; /* success */
38355+
4f0767ce 38356+out_free:
f0c0a007 38357+ if (sbinfo->si_xib_buf)
1c60b727 38358+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
38359+ sbinfo->si_xib_buf = NULL;
38360+ if (err >= 0)
38361+ err = -EIO;
4f0767ce 38362+out_unset:
b752ccd1
AM
38363+ fput(sbinfo->si_xib);
38364+ sbinfo->si_xib = NULL;
4f0767ce 38365+out:
062440b3 38366+ AuTraceErr(err);
b752ccd1 38367+ return err;
1facf9fc 38368+}
38369+
b752ccd1
AM
38370+/* xino for each branch */
38371+static void xino_clear_br(struct super_block *sb)
38372+{
5afbbe0d 38373+ aufs_bindex_t bindex, bbot;
b752ccd1 38374+ struct au_branch *br;
1facf9fc 38375+
5afbbe0d
AM
38376+ bbot = au_sbbot(sb);
38377+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1 38378+ br = au_sbr(sb, bindex);
062440b3
AM
38379+ AuDebugOn(!br);
38380+ au_xino_put(br);
38381+ }
38382+}
38383+
38384+static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br,
38385+ aufs_bindex_t bshared)
38386+{
38387+ struct au_branch *brshared;
b752ccd1 38388+
062440b3
AM
38389+ brshared = au_sbr(sb, bshared);
38390+ AuDebugOn(!brshared->br_xino);
38391+ AuDebugOn(!brshared->br_xino->xi_file);
38392+ if (br->br_xino != brshared->br_xino) {
38393+ au_xino_get(brshared);
38394+ au_xino_put(br);
38395+ br->br_xino = brshared->br_xino;
b752ccd1
AM
38396+ }
38397+}
38398+
062440b3
AM
38399+struct au_xino_do_set_br {
38400+ vfs_writef_t writef;
38401+ struct au_branch *br;
38402+ ino_t h_ino;
38403+ aufs_bindex_t bshared;
38404+};
38405+
38406+static int au_xino_do_set_br(struct super_block *sb, struct path *path,
38407+ struct au_xino_do_set_br *args)
1facf9fc 38408+{
38409+ int err;
acd2b654 38410+ struct au_xi_calc calc;
062440b3 38411+ struct file *file;
acd2b654
AM
38412+ struct au_branch *br;
38413+ struct au_xi_new xinew = {
38414+ .base = path
38415+ };
062440b3 38416+
acd2b654
AM
38417+ br = args->br;
38418+ xinew.xi = br->br_xino;
38419+ au_xi_calc(sb, args->h_ino, &calc);
38420+ xinew.copy_src = au_xino_file(xinew.xi, calc.idx);
38421+ if (args->bshared >= 0)
062440b3 38422+ /* shared xino */
acd2b654
AM
38423+ au_xino_set_br_shared(sb, br, args->bshared);
38424+ else if (!xinew.xi) {
38425+ /* new xino */
38426+ err = au_xino_init(br, calc.idx, xinew.copy_src);
38427+ if (unlikely(err))
38428+ goto out;
062440b3
AM
38429+ }
38430+
acd2b654
AM
38431+ /* force re-creating */
38432+ xinew.xi = br->br_xino;
38433+ xinew.idx = calc.idx;
38434+ mutex_lock(&xinew.xi->xi_mtx);
38435+ file = au_xi_new(sb, &xinew);
38436+ mutex_unlock(&xinew.xi->xi_mtx);
062440b3
AM
38437+ err = PTR_ERR(file);
38438+ if (IS_ERR(file))
38439+ goto out;
acd2b654
AM
38440+ AuDebugOn(!file);
38441+
38442+ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO);
38443+ if (unlikely(err))
38444+ au_xino_put(br);
062440b3 38445+
062440b3
AM
38446+out:
38447+ AuTraceErr(err);
38448+ return err;
38449+}
38450+
38451+static int au_xino_set_br(struct super_block *sb, struct path *path)
38452+{
38453+ int err;
38454+ aufs_bindex_t bindex, bbot;
38455+ struct au_xino_do_set_br args;
b752ccd1 38456+ struct inode *inode;
1facf9fc 38457+
b752ccd1
AM
38458+ SiMustWriteLock(sb);
38459+
5afbbe0d 38460+ bbot = au_sbbot(sb);
5527c038 38461+ inode = d_inode(sb->s_root);
062440b3
AM
38462+ args.writef = au_sbi(sb)->si_xwrite;
38463+ for (bindex = 0; bindex <= bbot; bindex++) {
38464+ args.h_ino = au_h_iptr(inode, bindex)->i_ino;
38465+ args.br = au_sbr(sb, bindex);
38466+ args.bshared = is_sb_shared(sb, bindex, bindex - 1);
38467+ err = au_xino_do_set_br(sb, path, &args);
b752ccd1 38468+ if (unlikely(err))
062440b3 38469+ break;
b752ccd1 38470+ }
1facf9fc 38471+
062440b3 38472+ AuTraceErr(err);
1facf9fc 38473+ return err;
38474+}
b752ccd1
AM
38475+
38476+void au_xino_clr(struct super_block *sb)
38477+{
38478+ struct au_sbinfo *sbinfo;
38479+
38480+ au_xigen_clr(sb);
38481+ xino_clear_xib(sb);
38482+ xino_clear_br(sb);
062440b3 38483+ dbgaufs_brs_del(sb, 0);
b752ccd1
AM
38484+ sbinfo = au_sbi(sb);
38485+ /* lvalue, do not call au_mntflags() */
38486+ au_opt_clr(sbinfo->si_mntflags, XINO);
38487+}
38488+
062440b3 38489+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount)
b752ccd1
AM
38490+{
38491+ int err, skip;
062440b3 38492+ struct dentry *dentry, *parent, *cur_dentry, *cur_parent;
b752ccd1
AM
38493+ struct qstr *dname, *cur_name;
38494+ struct file *cur_xino;
b752ccd1 38495+ struct au_sbinfo *sbinfo;
062440b3 38496+ struct path *path, *cur_path;
b752ccd1
AM
38497+
38498+ SiMustWriteLock(sb);
38499+
38500+ err = 0;
38501+ sbinfo = au_sbi(sb);
062440b3
AM
38502+ path = &xiopt->file->f_path;
38503+ dentry = path->dentry;
38504+ parent = dget_parent(dentry);
b752ccd1
AM
38505+ if (remount) {
38506+ skip = 0;
b752ccd1
AM
38507+ cur_xino = sbinfo->si_xib;
38508+ if (cur_xino) {
062440b3
AM
38509+ cur_path = &cur_xino->f_path;
38510+ cur_dentry = cur_path->dentry;
38511+ cur_parent = dget_parent(cur_dentry);
38512+ cur_name = &cur_dentry->d_name;
38513+ dname = &dentry->d_name;
b752ccd1 38514+ skip = (cur_parent == parent
38d290e6 38515+ && au_qstreq(dname, cur_name));
b752ccd1
AM
38516+ dput(cur_parent);
38517+ }
38518+ if (skip)
38519+ goto out;
38520+ }
38521+
38522+ au_opt_set(sbinfo->si_mntflags, XINO);
062440b3
AM
38523+ err = au_xino_set_xib(sb, path);
38524+ /* si_x{read,write} are set */
b752ccd1 38525+ if (!err)
062440b3 38526+ err = au_xigen_set(sb, path);
b752ccd1 38527+ if (!err)
062440b3
AM
38528+ err = au_xino_set_br(sb, path);
38529+ if (!err) {
38530+ dbgaufs_brs_add(sb, 0, /*topdown*/1);
b752ccd1 38531+ goto out; /* success */
062440b3 38532+ }
b752ccd1
AM
38533+
38534+ /* reset all */
062440b3
AM
38535+ AuIOErr("failed setting xino(%d).\n", err);
38536+ au_xino_clr(sb);
b752ccd1 38537+
4f0767ce 38538+out:
b752ccd1
AM
38539+ dput(parent);
38540+ return err;
38541+}
38542+
b752ccd1
AM
38543+/*
38544+ * create a xinofile at the default place/path.
38545+ */
38546+struct file *au_xino_def(struct super_block *sb)
38547+{
38548+ struct file *file;
38549+ char *page, *p;
38550+ struct au_branch *br;
38551+ struct super_block *h_sb;
38552+ struct path path;
5afbbe0d 38553+ aufs_bindex_t bbot, bindex, bwr;
b752ccd1
AM
38554+
38555+ br = NULL;
5afbbe0d 38556+ bbot = au_sbbot(sb);
b752ccd1 38557+ bwr = -1;
5afbbe0d 38558+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1
AM
38559+ br = au_sbr(sb, bindex);
38560+ if (au_br_writable(br->br_perm)
86dc4139 38561+ && !au_test_fs_bad_xino(au_br_sb(br))) {
b752ccd1
AM
38562+ bwr = bindex;
38563+ break;
38564+ }
38565+ }
38566+
7f207e10
AM
38567+ if (bwr >= 0) {
38568+ file = ERR_PTR(-ENOMEM);
537831f9 38569+ page = (void *)__get_free_page(GFP_NOFS);
7f207e10
AM
38570+ if (unlikely(!page))
38571+ goto out;
86dc4139 38572+ path.mnt = au_br_mnt(br);
7f207e10
AM
38573+ path.dentry = au_h_dptr(sb->s_root, bwr);
38574+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
38575+ file = (void *)p;
38576+ if (!IS_ERR(p)) {
38577+ strcat(p, "/" AUFS_XINO_FNAME);
38578+ AuDbg("%s\n", p);
83b672a5 38579+ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1);
7f207e10 38580+ }
1c60b727 38581+ free_page((unsigned long)page);
7f207e10 38582+ } else {
83b672a5
AM
38583+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
38584+ /*wbrtop*/0);
7f207e10
AM
38585+ if (IS_ERR(file))
38586+ goto out;
2000de60 38587+ h_sb = file->f_path.dentry->d_sb;
7f207e10
AM
38588+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
38589+ pr_err("xino doesn't support %s(%s)\n",
38590+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
38591+ fput(file);
38592+ file = ERR_PTR(-EINVAL);
38593+ }
7f207e10 38594+ }
0c5527e5 38595+
7f207e10
AM
38596+out:
38597+ return file;
38598+}
38599+
38600+/* ---------------------------------------------------------------------- */
38601+
062440b3
AM
38602+/*
38603+ * initialize the xinofile for the specified branch @br
38604+ * at the place/path where @base_file indicates.
38605+ * test whether another branch is on the same filesystem or not,
38606+ * if found then share the xinofile with another branch.
38607+ */
38608+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
38609+ struct path *base)
7f207e10
AM
38610+{
38611+ int err;
062440b3
AM
38612+ struct au_xino_do_set_br args = {
38613+ .h_ino = h_ino,
38614+ .br = br
38615+ };
7f207e10 38616+
062440b3
AM
38617+ args.writef = au_sbi(sb)->si_xwrite;
38618+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb),
38619+ au_br_sb(br));
38620+ err = au_xino_do_set_br(sb, base, &args);
79b8bda9 38621+ if (unlikely(err))
062440b3 38622+ au_xino_put(br);
7f207e10 38623+
7f207e10
AM
38624+ return err;
38625+}
521ced18
JR
38626+
38627+/* ---------------------------------------------------------------------- */
38628+
062440b3
AM
38629+/*
38630+ * get an unused inode number from bitmap
38631+ */
38632+ino_t au_xino_new_ino(struct super_block *sb)
38633+{
38634+ ino_t ino;
38635+ unsigned long *p, pindex, ul, pend;
38636+ struct au_sbinfo *sbinfo;
38637+ struct file *file;
38638+ int free_bit, err;
38639+
38640+ if (!au_opt_test(au_mntflags(sb), XINO))
38641+ return iunique(sb, AUFS_FIRST_INO);
38642+
38643+ sbinfo = au_sbi(sb);
38644+ mutex_lock(&sbinfo->si_xib_mtx);
38645+ p = sbinfo->si_xib_buf;
38646+ free_bit = sbinfo->si_xib_next_bit;
38647+ if (free_bit < page_bits && !test_bit(free_bit, p))
38648+ goto out; /* success */
38649+ free_bit = find_first_zero_bit(p, page_bits);
38650+ if (free_bit < page_bits)
38651+ goto out; /* success */
38652+
38653+ pindex = sbinfo->si_xib_last_pindex;
38654+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
38655+ err = xib_pindex(sb, ul);
38656+ if (unlikely(err))
38657+ goto out_err;
38658+ free_bit = find_first_zero_bit(p, page_bits);
38659+ if (free_bit < page_bits)
38660+ goto out; /* success */
38661+ }
38662+
38663+ file = sbinfo->si_xib;
38664+ pend = vfsub_f_size_read(file) / PAGE_SIZE;
38665+ for (ul = pindex + 1; ul <= pend; ul++) {
38666+ err = xib_pindex(sb, ul);
38667+ if (unlikely(err))
38668+ goto out_err;
38669+ free_bit = find_first_zero_bit(p, page_bits);
38670+ if (free_bit < page_bits)
38671+ goto out; /* success */
38672+ }
38673+ BUG();
38674+
38675+out:
38676+ set_bit(free_bit, p);
38677+ sbinfo->si_xib_next_bit = free_bit + 1;
38678+ pindex = sbinfo->si_xib_last_pindex;
38679+ mutex_unlock(&sbinfo->si_xib_mtx);
38680+ ino = xib_calc_ino(pindex, free_bit);
38681+ AuDbg("i%lu\n", (unsigned long)ino);
38682+ return ino;
38683+out_err:
38684+ mutex_unlock(&sbinfo->si_xib_mtx);
38685+ AuDbg("i0\n");
38686+ return 0;
38687+}
38688+
38689+/* for s_op->delete_inode() */
38690+void au_xino_delete_inode(struct inode *inode, const int unlinked)
521ced18 38691+{
062440b3
AM
38692+ int err;
38693+ unsigned int mnt_flags;
38694+ aufs_bindex_t bindex, bbot, bi;
38695+ unsigned char try_trunc;
38696+ struct au_iinfo *iinfo;
38697+ struct super_block *sb;
38698+ struct au_hinode *hi;
38699+ struct inode *h_inode;
38700+ struct au_branch *br;
38701+ vfs_writef_t xwrite;
acd2b654
AM
38702+ struct au_xi_calc calc;
38703+ struct file *file;
521ced18 38704+
062440b3 38705+ AuDebugOn(au_is_bad_inode(inode));
521ced18 38706+
062440b3
AM
38707+ sb = inode->i_sb;
38708+ mnt_flags = au_mntflags(sb);
38709+ if (!au_opt_test(mnt_flags, XINO)
38710+ || inode->i_ino == AUFS_ROOT_INO)
38711+ return;
38712+
38713+ if (unlinked) {
38714+ au_xigen_inc(inode);
38715+ au_xib_clear_bit(inode);
38716+ }
38717+
38718+ iinfo = au_ii(inode);
38719+ bindex = iinfo->ii_btop;
38720+ if (bindex < 0)
38721+ return;
38722+
38723+ xwrite = au_sbi(sb)->si_xwrite;
38724+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
38725+ hi = au_hinode(iinfo, bindex);
38726+ bbot = iinfo->ii_bbot;
38727+ for (; bindex <= bbot; bindex++, hi++) {
38728+ h_inode = hi->hi_inode;
38729+ if (!h_inode
38730+ || (!unlinked && h_inode->i_nlink))
38731+ continue;
38732+
38733+ /* inode may not be revalidated */
38734+ bi = au_br_index(sb, hi->hi_id);
38735+ if (bi < 0)
38736+ continue;
38737+
38738+ br = au_sbr(sb, bi);
acd2b654
AM
38739+ au_xi_calc(sb, h_inode->i_ino, &calc);
38740+ file = au_xino_file(br->br_xino, calc.idx);
38741+ if (IS_ERR_OR_NULL(file))
38742+ continue;
38743+
38744+ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0);
062440b3
AM
38745+ if (!err && try_trunc
38746+ && au_test_fs_trunc_xino(au_br_sb(br)))
38747+ xino_try_trunc(sb, br);
38748+ }
521ced18
JR
38749+}
38750+
062440b3
AM
38751+/* ---------------------------------------------------------------------- */
38752+
38753+static int au_xinondir_find(struct au_xino *xi, ino_t h_ino)
521ced18
JR
38754+{
38755+ int found, total, i;
38756+
38757+ found = -1;
062440b3 38758+ total = xi->xi_nondir.total;
521ced18 38759+ for (i = 0; i < total; i++) {
062440b3 38760+ if (xi->xi_nondir.array[i] != h_ino)
521ced18
JR
38761+ continue;
38762+ found = i;
38763+ break;
38764+ }
38765+
38766+ return found;
38767+}
38768+
062440b3 38769+static int au_xinondir_expand(struct au_xino *xi)
521ced18
JR
38770+{
38771+ int err, sz;
38772+ ino_t *p;
38773+
38774+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX);
38775+
38776+ err = -ENOMEM;
062440b3 38777+ sz = xi->xi_nondir.total * sizeof(ino_t);
521ced18
JR
38778+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2))
38779+ goto out;
062440b3 38780+ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC,
521ced18
JR
38781+ /*may_shrink*/0);
38782+ if (p) {
062440b3
AM
38783+ xi->xi_nondir.array = p;
38784+ xi->xi_nondir.total <<= 1;
38785+ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total);
521ced18
JR
38786+ err = 0;
38787+ }
38788+
38789+out:
38790+ return err;
38791+}
38792+
062440b3
AM
38793+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
38794+ ino_t h_ino, int idx)
38795+{
38796+ struct au_xino *xi;
38797+
38798+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
38799+ xi = au_sbr(sb, bindex)->br_xino;
38800+ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx);
38801+
38802+ spin_lock(&xi->xi_nondir.spin);
38803+ AuDebugOn(xi->xi_nondir.array[idx] != h_ino);
38804+ xi->xi_nondir.array[idx] = 0;
38805+ spin_unlock(&xi->xi_nondir.spin);
38806+ wake_up_all(&xi->xi_nondir.wqh);
38807+}
38808+
521ced18
JR
38809+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
38810+ int *idx)
38811+{
38812+ int err, found, empty;
062440b3 38813+ struct au_xino *xi;
521ced18
JR
38814+
38815+ err = 0;
38816+ *idx = -1;
38817+ if (!au_opt_test(au_mntflags(sb), XINO))
38818+ goto out; /* no xino */
38819+
062440b3 38820+ xi = au_sbr(sb, bindex)->br_xino;
521ced18
JR
38821+
38822+again:
062440b3
AM
38823+ spin_lock(&xi->xi_nondir.spin);
38824+ found = au_xinondir_find(xi, h_ino);
521ced18 38825+ if (found == -1) {
062440b3 38826+ empty = au_xinondir_find(xi, /*h_ino*/0);
521ced18 38827+ if (empty == -1) {
062440b3
AM
38828+ empty = xi->xi_nondir.total;
38829+ err = au_xinondir_expand(xi);
521ced18
JR
38830+ if (unlikely(err))
38831+ goto out_unlock;
38832+ }
062440b3 38833+ xi->xi_nondir.array[empty] = h_ino;
521ced18
JR
38834+ *idx = empty;
38835+ } else {
062440b3
AM
38836+ spin_unlock(&xi->xi_nondir.spin);
38837+ wait_event(xi->xi_nondir.wqh,
38838+ xi->xi_nondir.array[found] != h_ino);
521ced18
JR
38839+ goto again;
38840+ }
38841+
38842+out_unlock:
062440b3
AM
38843+ spin_unlock(&xi->xi_nondir.spin);
38844+out:
38845+ return err;
38846+}
38847+
38848+/* ---------------------------------------------------------------------- */
38849+
38850+int au_xino_path(struct seq_file *seq, struct file *file)
38851+{
38852+ int err;
38853+
38854+ err = au_seq_path(seq, &file->f_path);
38855+ if (unlikely(err))
38856+ goto out;
38857+
38858+#define Deleted "\\040(deleted)"
38859+ seq->count -= sizeof(Deleted) - 1;
38860+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
38861+ sizeof(Deleted) - 1));
38862+#undef Deleted
38863+
521ced18
JR
38864+out:
38865+ return err;
38866+}
537831f9 38867diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h
fbc438ed
JR
38868--- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 08:00:00.000000000 +0800
38869+++ linux/include/uapi/linux/aufs_type.h 2019-07-11 21:21:54.382384486 +0800
062440b3
AM
38870@@ -0,0 +1,448 @@
38871+/* SPDX-License-Identifier: GPL-2.0 */
7f207e10 38872+/*
ba1aed25 38873+ * Copyright (C) 2005-2019 Junjiro R. Okajima
7f207e10
AM
38874+ *
38875+ * This program, aufs is free software; you can redistribute it and/or modify
38876+ * it under the terms of the GNU General Public License as published by
38877+ * the Free Software Foundation; either version 2 of the License, or
38878+ * (at your option) any later version.
38879+ *
38880+ * This program is distributed in the hope that it will be useful,
38881+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
38882+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38883+ * GNU General Public License for more details.
38884+ *
38885+ * You should have received a copy of the GNU General Public License
523b37e3 38886+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
38887+ */
38888+
38889+#ifndef __AUFS_TYPE_H__
38890+#define __AUFS_TYPE_H__
38891+
f6c5ef8b
AM
38892+#define AUFS_NAME "aufs"
38893+
9dbd164d 38894+#ifdef __KERNEL__
f6c5ef8b
AM
38895+/*
38896+ * define it before including all other headers.
38897+ * sched.h may use pr_* macros before defining "current", so define the
38898+ * no-current version first, and re-define later.
38899+ */
38900+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
38901+#include <linux/sched.h>
38902+#undef pr_fmt
a2a7ad62
AM
38903+#define pr_fmt(fmt) \
38904+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \
38905+ (int)sizeof(current->comm), current->comm, current->pid
9dbd164d
AM
38906+#else
38907+#include <stdint.h>
38908+#include <sys/types.h>
f6c5ef8b 38909+#endif /* __KERNEL__ */
7f207e10 38910+
f6c5ef8b
AM
38911+#include <linux/limits.h>
38912+
fbc438ed 38913+#define AUFS_VERSION "5.x-rcN-20190610"
7f207e10
AM
38914+
38915+/* todo? move this to linux-2.6.19/include/magic.h */
38916+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
38917+
38918+/* ---------------------------------------------------------------------- */
38919+
38920+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 38921+typedef int8_t aufs_bindex_t;
7f207e10
AM
38922+#define AUFS_BRANCH_MAX 127
38923+#else
9dbd164d 38924+typedef int16_t aufs_bindex_t;
7f207e10
AM
38925+#ifdef CONFIG_AUFS_BRANCH_MAX_511
38926+#define AUFS_BRANCH_MAX 511
38927+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
38928+#define AUFS_BRANCH_MAX 1023
38929+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
38930+#define AUFS_BRANCH_MAX 32767
38931+#endif
38932+#endif
38933+
38934+#ifdef __KERNEL__
38935+#ifndef AUFS_BRANCH_MAX
38936+#error unknown CONFIG_AUFS_BRANCH_MAX value
38937+#endif
38938+#endif /* __KERNEL__ */
38939+
38940+/* ---------------------------------------------------------------------- */
38941+
7f207e10
AM
38942+#define AUFS_FSTYPE AUFS_NAME
38943+
38944+#define AUFS_ROOT_INO 2
38945+#define AUFS_FIRST_INO 11
38946+
38947+#define AUFS_WH_PFX ".wh."
38948+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
38949+#define AUFS_WH_TMP_LEN 4
86dc4139 38950+/* a limit for rmdir/rename a dir and copyup */
7f207e10
AM
38951+#define AUFS_MAX_NAMELEN (NAME_MAX \
38952+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
38953+ - 1 /* dot */\
38954+ - AUFS_WH_TMP_LEN) /* hex */
38955+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
38956+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
392086de
AM
38957+#define AUFS_XINO_DEF_SEC 30 /* seconds */
38958+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */
7f207e10
AM
38959+#define AUFS_DIRWH_DEF 3
38960+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 38961+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
38962+#define AUFS_RDBLK_DEF 512 /* bytes */
38963+#define AUFS_RDHASH_DEF 32
38964+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
38965+#define AUFS_MFS_DEF_SEC 30 /* seconds */
38966+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
076b876e 38967+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */
86dc4139 38968+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */
7f207e10
AM
38969+
38970+/* pseudo-link maintenace under /proc */
38971+#define AUFS_PLINK_MAINT_NAME "plink_maint"
38972+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
38973+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
38974+
8b6a4947
AM
38975+/* dirren, renamed dir */
38976+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr."
38977+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino"
38978+/* whiteouted doubly */
38979+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX
38980+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME
38981+
7f207e10
AM
38982+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
38983+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
38984+
38985+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
38986+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
38987+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
38988+
38989+/* doubly whiteouted */
38990+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
38991+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
38992+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
38993+
1e00d052 38994+/* branch permissions and attributes */
7f207e10
AM
38995+#define AUFS_BRPERM_RW "rw"
38996+#define AUFS_BRPERM_RO "ro"
38997+#define AUFS_BRPERM_RR "rr"
076b876e
AM
38998+#define AUFS_BRATTR_COO_REG "coo_reg"
38999+#define AUFS_BRATTR_COO_ALL "coo_all"
39000+#define AUFS_BRATTR_FHSM "fhsm"
39001+#define AUFS_BRATTR_UNPIN "unpin"
c1595e42
JR
39002+#define AUFS_BRATTR_ICEX "icex"
39003+#define AUFS_BRATTR_ICEX_SEC "icexsec"
39004+#define AUFS_BRATTR_ICEX_SYS "icexsys"
39005+#define AUFS_BRATTR_ICEX_TR "icextr"
39006+#define AUFS_BRATTR_ICEX_USR "icexusr"
39007+#define AUFS_BRATTR_ICEX_OTH "icexoth"
1e00d052
AM
39008+#define AUFS_BRRATTR_WH "wh"
39009+#define AUFS_BRWATTR_NLWH "nolwh"
076b876e
AM
39010+#define AUFS_BRWATTR_MOO "moo"
39011+
39012+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
39013+#define AuBrPerm_RO (1 << 1) /* readonly */
39014+#define AuBrPerm_RR (1 << 2) /* natively readonly */
39015+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
39016+
39017+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */
39018+#define AuBrAttr_COO_ALL (1 << 4)
39019+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL)
39020+
39021+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */
39022+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of
c1595e42
JR
39023+ branch. meaningless since
39024+ linux-3.18-rc1 */
39025+
39026+/* ignore error in copying XATTR */
39027+#define AuBrAttr_ICEX_SEC (1 << 7)
39028+#define AuBrAttr_ICEX_SYS (1 << 8)
39029+#define AuBrAttr_ICEX_TR (1 << 9)
39030+#define AuBrAttr_ICEX_USR (1 << 10)
39031+#define AuBrAttr_ICEX_OTH (1 << 11)
39032+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \
39033+ | AuBrAttr_ICEX_SYS \
39034+ | AuBrAttr_ICEX_TR \
39035+ | AuBrAttr_ICEX_USR \
39036+ | AuBrAttr_ICEX_OTH)
39037+
39038+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */
076b876e
AM
39039+#define AuBrRAttr_Mask AuBrRAttr_WH
39040+
c1595e42
JR
39041+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */
39042+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */
076b876e
AM
39043+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO)
39044+
39045+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO)
39046+
c1595e42 39047+/* #warning test userspace */
076b876e
AM
39048+#ifdef __KERNEL__
39049+#ifndef CONFIG_AUFS_FHSM
39050+#undef AuBrAttr_FHSM
39051+#define AuBrAttr_FHSM 0
39052+#endif
c1595e42
JR
39053+#ifndef CONFIG_AUFS_XATTR
39054+#undef AuBrAttr_ICEX
39055+#define AuBrAttr_ICEX 0
39056+#undef AuBrAttr_ICEX_SEC
39057+#define AuBrAttr_ICEX_SEC 0
39058+#undef AuBrAttr_ICEX_SYS
39059+#define AuBrAttr_ICEX_SYS 0
39060+#undef AuBrAttr_ICEX_TR
39061+#define AuBrAttr_ICEX_TR 0
39062+#undef AuBrAttr_ICEX_USR
39063+#define AuBrAttr_ICEX_USR 0
39064+#undef AuBrAttr_ICEX_OTH
39065+#define AuBrAttr_ICEX_OTH 0
39066+#endif
076b876e
AM
39067+#endif
39068+
39069+/* the longest combination */
c1595e42
JR
39070+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */
39071+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \
39072+ "+" AUFS_BRATTR_COO_REG \
39073+ "+" AUFS_BRATTR_FHSM \
39074+ "+" AUFS_BRATTR_UNPIN \
7e9cd9fe
AM
39075+ "+" AUFS_BRATTR_ICEX_SEC \
39076+ "+" AUFS_BRATTR_ICEX_SYS \
39077+ "+" AUFS_BRATTR_ICEX_USR \
39078+ "+" AUFS_BRATTR_ICEX_OTH \
076b876e
AM
39079+ "+" AUFS_BRWATTR_NLWH)
39080+
39081+typedef struct {
39082+ char a[AuBrPermStrSz];
39083+} au_br_perm_str_t;
39084+
39085+static inline int au_br_writable(int brperm)
39086+{
39087+ return brperm & AuBrPerm_RW;
39088+}
39089+
39090+static inline int au_br_whable(int brperm)
39091+{
39092+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
39093+}
39094+
39095+static inline int au_br_wh_linkable(int brperm)
39096+{
39097+ return !(brperm & AuBrWAttr_NoLinkWH);
39098+}
39099+
39100+static inline int au_br_cmoo(int brperm)
39101+{
39102+ return brperm & AuBrAttr_CMOO_Mask;
39103+}
39104+
39105+static inline int au_br_fhsm(int brperm)
39106+{
39107+ return brperm & AuBrAttr_FHSM;
39108+}
7f207e10
AM
39109+
39110+/* ---------------------------------------------------------------------- */
39111+
39112+/* ioctl */
39113+enum {
39114+ /* readdir in userspace */
39115+ AuCtl_RDU,
39116+ AuCtl_RDU_INO,
39117+
076b876e
AM
39118+ AuCtl_WBR_FD, /* pathconf wrapper */
39119+ AuCtl_IBUSY, /* busy inode */
39120+ AuCtl_MVDOWN, /* move-down */
39121+ AuCtl_BR, /* info about branches */
39122+ AuCtl_FHSM_FD /* connection for fhsm */
7f207e10
AM
39123+};
39124+
39125+/* borrowed from linux/include/linux/kernel.h */
39126+#ifndef ALIGN
39127+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
39128+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
39129+#endif
39130+
39131+/* borrowed from linux/include/linux/compiler-gcc3.h */
39132+#ifndef __aligned
39133+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
39134+#endif
39135+
39136+#ifdef __KERNEL__
39137+#ifndef __packed
7f207e10
AM
39138+#define __packed __attribute__((packed))
39139+#endif
53392da6 39140+#endif
7f207e10
AM
39141+
39142+struct au_rdu_cookie {
9dbd164d
AM
39143+ uint64_t h_pos;
39144+ int16_t bindex;
39145+ uint8_t flags;
39146+ uint8_t pad;
39147+ uint32_t generation;
7f207e10
AM
39148+} __aligned(8);
39149+
39150+struct au_rdu_ent {
9dbd164d
AM
39151+ uint64_t ino;
39152+ int16_t bindex;
39153+ uint8_t type;
39154+ uint8_t nlen;
39155+ uint8_t wh;
7f207e10
AM
39156+ char name[0];
39157+} __aligned(8);
39158+
39159+static inline int au_rdu_len(int nlen)
39160+{
39161+ /* include the terminating NULL */
39162+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 39163+ sizeof(uint64_t));
7f207e10
AM
39164+}
39165+
39166+union au_rdu_ent_ul {
39167+ struct au_rdu_ent __user *e;
9dbd164d 39168+ uint64_t ul;
7f207e10
AM
39169+};
39170+
39171+enum {
39172+ AufsCtlRduV_SZ,
39173+ AufsCtlRduV_End
39174+};
39175+
39176+struct aufs_rdu {
39177+ /* input */
39178+ union {
9dbd164d
AM
39179+ uint64_t sz; /* AuCtl_RDU */
39180+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
39181+ };
39182+ union au_rdu_ent_ul ent;
9dbd164d 39183+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
39184+
39185+ /* input/output */
9dbd164d 39186+ uint32_t blk;
7f207e10
AM
39187+
39188+ /* output */
39189+ union au_rdu_ent_ul tail;
39190+ /* number of entries which were added in a single call */
9dbd164d
AM
39191+ uint64_t rent;
39192+ uint8_t full;
39193+ uint8_t shwh;
7f207e10
AM
39194+
39195+ struct au_rdu_cookie cookie;
39196+} __aligned(8);
39197+
1e00d052
AM
39198+/* ---------------------------------------------------------------------- */
39199+
8b6a4947
AM
39200+/* dirren. the branch is identified by the filename who contains this */
39201+struct au_drinfo {
39202+ uint64_t ino;
39203+ union {
39204+ uint8_t oldnamelen;
39205+ uint64_t _padding;
39206+ };
39207+ uint8_t oldname[0];
39208+} __aligned(8);
39209+
39210+struct au_drinfo_fdata {
39211+ uint32_t magic;
39212+ struct au_drinfo drinfo;
39213+} __aligned(8);
39214+
39215+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01)
39216+/* future */
39217+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02)
39218+
39219+/* ---------------------------------------------------------------------- */
39220+
1e00d052 39221+struct aufs_wbr_fd {
9dbd164d
AM
39222+ uint32_t oflags;
39223+ int16_t brid;
1e00d052
AM
39224+} __aligned(8);
39225+
39226+/* ---------------------------------------------------------------------- */
39227+
027c5e7a 39228+struct aufs_ibusy {
9dbd164d
AM
39229+ uint64_t ino, h_ino;
39230+ int16_t bindex;
027c5e7a
AM
39231+} __aligned(8);
39232+
1e00d052
AM
39233+/* ---------------------------------------------------------------------- */
39234+
392086de
AM
39235+/* error code for move-down */
39236+/* the actual message strings are implemented in aufs-util.git */
39237+enum {
39238+ EAU_MVDOWN_OPAQUE = 1,
39239+ EAU_MVDOWN_WHITEOUT,
39240+ EAU_MVDOWN_UPPER,
39241+ EAU_MVDOWN_BOTTOM,
39242+ EAU_MVDOWN_NOUPPER,
39243+ EAU_MVDOWN_NOLOWERBR,
39244+ EAU_Last
39245+};
39246+
c2b27bf2 39247+/* flags for move-down */
392086de
AM
39248+#define AUFS_MVDOWN_DMSG 1
39249+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */
39250+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */
39251+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */
39252+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */
39253+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */
39254+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */
39255+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */
39256+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */
076b876e
AM
39257+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */
39258+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */
39259+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */
39260+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */
c2b27bf2 39261+
076b876e 39262+/* index for move-down */
392086de
AM
39263+enum {
39264+ AUFS_MVDOWN_UPPER,
39265+ AUFS_MVDOWN_LOWER,
39266+ AUFS_MVDOWN_NARRAY
39267+};
39268+
076b876e
AM
39269+/*
39270+ * additional info of move-down
39271+ * number of free blocks and inodes.
39272+ * subset of struct kstatfs, but smaller and always 64bit.
39273+ */
39274+struct aufs_stfs {
39275+ uint64_t f_blocks;
39276+ uint64_t f_bavail;
39277+ uint64_t f_files;
39278+ uint64_t f_ffree;
39279+};
39280+
39281+struct aufs_stbr {
39282+ int16_t brid; /* optional input */
39283+ int16_t bindex; /* output */
39284+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */
39285+} __aligned(8);
39286+
c2b27bf2 39287+struct aufs_mvdown {
076b876e
AM
39288+ uint32_t flags; /* input/output */
39289+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */
39290+ int8_t au_errno; /* output */
39291+} __aligned(8);
39292+
39293+/* ---------------------------------------------------------------------- */
39294+
39295+union aufs_brinfo {
39296+ /* PATH_MAX may differ between kernel-space and user-space */
39297+ char _spacer[4096];
392086de 39298+ struct {
076b876e
AM
39299+ int16_t id;
39300+ int perm;
39301+ char path[0];
39302+ };
c2b27bf2
AM
39303+} __aligned(8);
39304+
39305+/* ---------------------------------------------------------------------- */
39306+
7f207e10
AM
39307+#define AuCtlType 'A'
39308+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
39309+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
39310+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
39311+ struct aufs_wbr_fd)
027c5e7a 39312+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
392086de
AM
39313+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \
39314+ struct aufs_mvdown)
076b876e
AM
39315+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo)
39316+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int)
7f207e10
AM
39317+
39318+#endif /* __AUFS_TYPE_H__ */
2121bcd9 39319SPDX-License-Identifier: GPL-2.0
fbc438ed 39320aufs5.x-rcN loopback patch
5527c038
JR
39321
39322diff --git a/drivers/block/loop.c b/drivers/block/loop.c
fbc438ed 39323index 1b723737592b..16561a96019c 100644
5527c038
JR
39324--- a/drivers/block/loop.c
39325+++ b/drivers/block/loop.c
fbc438ed 39326@@ -633,6 +633,15 @@ static inline void loop_update_dio(struct loop_device *lo)
8b6a4947 39327 lo->use_dio);
5527c038
JR
39328 }
39329
5527c038
JR
39330+static struct file *loop_real_file(struct file *file)
39331+{
39332+ struct file *f = NULL;
39333+
39334+ if (file->f_path.dentry->d_sb->s_op->real_loop)
39335+ f = file->f_path.dentry->d_sb->s_op->real_loop(file);
39336+ return f;
8b6a4947
AM
39337+}
39338+
c2c0f25c 39339 static void loop_reread_partitions(struct loop_device *lo,
8b6a4947
AM
39340 struct block_device *bdev)
39341 {
fbc438ed 39342@@ -686,6 +695,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
5527c038
JR
39343 unsigned int arg)
39344 {
e1106418 39345 struct file *file = NULL, *old_file;
5527c038 39346+ struct file *f, *virt_file = NULL, *old_virt_file;
5527c038 39347 int error;
ba1aed25 39348 bool partscan;
5527c038 39349
fbc438ed 39350@@ -705,12 +715,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
cd7a4cd9
AM
39351 file = fget(arg);
39352 if (!file)
e1106418 39353 goto out_err;
5527c038
JR
39354+ f = loop_real_file(file);
39355+ if (f) {
39356+ virt_file = file;
39357+ file = f;
39358+ get_file(file);
39359+ }
39360
cd7a4cd9
AM
39361 error = loop_validate_file(file, bdev);
39362 if (error)
e1106418 39363 goto out_err;
cd7a4cd9 39364
5527c038
JR
39365 old_file = lo->lo_backing_file;
39366+ old_virt_file = lo->lo_backing_virt_file;
39367
39368 error = -EINVAL;
39369
fbc438ed 39370@@ -722,6 +739,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
8b6a4947
AM
39371 blk_mq_freeze_queue(lo->lo_queue);
39372 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
39373 lo->lo_backing_file = file;
39374+ lo->lo_backing_virt_file = virt_file;
39375 lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
39376 mapping_set_gfp_mask(file->f_mapping,
39377 lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
fbc438ed 39378@@ -735,6 +753,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
e1106418
JR
39379 * dependency.
39380 */
5527c038
JR
39381 fput(old_file);
39382+ if (old_virt_file)
39383+ fput(old_virt_file);
e1106418 39384 if (partscan)
c2c0f25c 39385 loop_reread_partitions(lo, bdev);
5527c038 39386 return 0;
fbc438ed 39387@@ -743,6 +763,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
e1106418
JR
39388 mutex_unlock(&loop_ctl_mutex);
39389 if (file)
39390 fput(file);
5527c038
JR
39391+ if (virt_file)
39392+ fput(virt_file);
5527c038
JR
39393 return error;
39394 }
e1106418 39395
fbc438ed 39396@@ -947,7 +969,7 @@ static void loop_update_rotational(struct loop_device *lo)
5527c038
JR
39397 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
39398 struct block_device *bdev, unsigned int arg)
39399 {
062440b3 39400- struct file *file;
5527c038
JR
39401+ struct file *file, *f, *virt_file = NULL;
39402 struct inode *inode;
39403 struct address_space *mapping;
8b6a4947 39404 int lo_flags = 0;
fbc438ed 39405@@ -962,6 +984,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
5527c038
JR
39406 file = fget(arg);
39407 if (!file)
39408 goto out;
39409+ f = loop_real_file(file);
39410+ if (f) {
39411+ virt_file = file;
39412+ file = f;
39413+ get_file(file);
39414+ }
39415
fbc438ed
JR
39416 /*
39417 * If we don't hold exclusive handle for the device, upgrade to it
39418@@ -1009,6 +1037,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
5527c038
JR
39419 lo->lo_device = bdev;
39420 lo->lo_flags = lo_flags;
39421 lo->lo_backing_file = file;
39422+ lo->lo_backing_virt_file = virt_file;
39423 lo->transfer = NULL;
39424 lo->ioctl = NULL;
39425 lo->lo_sizelimit = 0;
fbc438ed
JR
39426@@ -1052,6 +1081,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
39427 blkdev_put(bdev, mode | FMODE_EXCL);
e1106418 39428 out_putf:
5527c038
JR
39429 fput(file);
39430+ if (virt_file)
39431+ fput(virt_file);
e1106418 39432 out:
5527c038
JR
39433 /* This is safe: open() is still holding a reference. */
39434 module_put(THIS_MODULE);
fbc438ed 39435@@ -1098,6 +1129,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
ba1aed25 39436 static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39437 {
e1106418 39438 struct file *filp = NULL;
5527c038
JR
39439+ struct file *virt_filp = lo->lo_backing_virt_file;
39440 gfp_t gfp = lo->old_gfp_mask;
39441 struct block_device *bdev = lo->lo_device;
ba1aed25 39442 int err = 0;
fbc438ed 39443@@ -1121,6 +1153,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39444
5527c038 39445 spin_lock_irq(&lo->lo_lock);
5527c038
JR
39446 lo->lo_backing_file = NULL;
39447+ lo->lo_backing_virt_file = NULL;
39448 spin_unlock_irq(&lo->lo_lock);
39449
39450 loop_release_xfer(lo);
fbc438ed 39451@@ -1203,6 +1236,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39452 */
e1106418
JR
39453 if (filp)
39454 fput(filp);
5527c038
JR
39455+ if (virt_filp)
39456+ fput(virt_filp);
e1106418 39457 return err;
5527c038
JR
39458 }
39459
39460diff --git a/drivers/block/loop.h b/drivers/block/loop.h
ba1aed25 39461index af75a5ee4094..1e6ee5a4f623 100644
5527c038
JR
39462--- a/drivers/block/loop.h
39463+++ b/drivers/block/loop.h
39464@@ -46,7 +46,7 @@ struct loop_device {
39465 int (*ioctl)(struct loop_device *, int cmd,
39466 unsigned long arg);
39467
39468- struct file * lo_backing_file;
39469+ struct file * lo_backing_file, *lo_backing_virt_file;
39470 struct block_device *lo_device;
5527c038 39471 void *key_data;
8b6a4947 39472
5527c038 39473diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
ba1aed25 39474index 0309f0d502ff..19feb4f3cb5f 100644
5527c038
JR
39475--- a/fs/aufs/f_op.c
39476+++ b/fs/aufs/f_op.c
acd2b654 39477@@ -359,7 +359,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
5527c038
JR
39478 if (IS_ERR(h_file))
39479 goto out;
39480
39481- if (au_test_loopback_kthread()) {
39482+ if (0 && au_test_loopback_kthread()) {
39483 au_warn_loopback(h_file->f_path.dentry->d_sb);
39484 if (file->f_mapping != h_file->f_mapping) {
39485 file->f_mapping = h_file->f_mapping;
39486diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
fbc438ed 39487index 9ba35a878ecd..4ed0ff03d5ab 100644
5527c038
JR
39488--- a/fs/aufs/loop.c
39489+++ b/fs/aufs/loop.c
2121bcd9 39490@@ -133,3 +133,19 @@ void au_loopback_fin(void)
79b8bda9 39491 symbol_put(loop_backing_file);
9f237c51 39492 au_kfree_try_rcu(au_warn_loopback_array);
5527c038
JR
39493 }
39494+
39495+/* ---------------------------------------------------------------------- */
39496+
39497+/* support the loopback block device insude aufs */
39498+
39499+struct file *aufs_real_loop(struct file *file)
39500+{
39501+ struct file *f;
39502+
39503+ BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb));
39504+ fi_read_lock(file);
39505+ f = au_hf_top(file);
39506+ fi_read_unlock(file);
39507+ AuDebugOn(!f);
39508+ return f;
39509+}
39510diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
83b672a5 39511index f31e40aff267..e13fb1a0717a 100644
5527c038
JR
39512--- a/fs/aufs/loop.h
39513+++ b/fs/aufs/loop.h
eca801bf 39514@@ -26,6 +26,8 @@ void au_warn_loopback(struct super_block *h_sb);
5527c038
JR
39515
39516 int au_loopback_init(void);
39517 void au_loopback_fin(void);
39518+
39519+struct file *aufs_real_loop(struct file *file);
39520 #else
83b672a5 39521 AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf
AM
39522
39523@@ -36,6 +38,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb)
5527c038
JR
39524
39525 AuStubInt0(au_loopback_init, void)
39526 AuStubVoid(au_loopback_fin, void)
39527+
39528+AuStub(struct file *, aufs_real_loop, return NULL, struct file *file)
39529 #endif /* BLK_DEV_LOOP */
39530
39531 #endif /* __KERNEL__ */
39532diff --git a/fs/aufs/super.c b/fs/aufs/super.c
fbc438ed 39533index a97e2921cb09..f74eb6962684 100644
5527c038
JR
39534--- a/fs/aufs/super.c
39535+++ b/fs/aufs/super.c
fbc438ed 39536@@ -844,7 +844,10 @@ static const struct super_operations aufs_sop = {
5527c038
JR
39537 .statfs = aufs_statfs,
39538 .put_super = aufs_put_super,
39539 .sync_fs = aufs_sync_fs,
39540- .remount_fs = aufs_remount_fs
39541+ .remount_fs = aufs_remount_fs,
39542+#ifdef CONFIG_AUFS_BDEV_LOOP
39543+ .real_loop = aufs_real_loop
39544+#endif
39545 };
39546
39547 /* ---------------------------------------------------------------------- */
39548diff --git a/include/linux/fs.h b/include/linux/fs.h
fbc438ed 39549index 28593b894e7b..bdc2611787df 100644
5527c038
JR
39550--- a/include/linux/fs.h
39551+++ b/include/linux/fs.h
fbc438ed 39552@@ -1947,6 +1947,10 @@ struct super_operations {
5527c038
JR
39553 struct shrink_control *);
39554 long (*free_cached_objects)(struct super_block *,
39555 struct shrink_control *);
39556+#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
39557+ /* and aufs */
39558+ struct file *(*real_loop)(struct file *);
39559+#endif
39560 };
39561
39562 /*
This page took 7.047368 seconds and 4 git commands to generate.