aufs5-loopback.patch 7.12 KB
Newer Older
J. R. Okajima's avatar
J. R. Okajima committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
SPDX-License-Identifier: GPL-2.0
aufs5.4.3 loopback patch

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 5e094699215e..22b2ecb6cfe8 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -625,6 +625,15 @@ static inline void loop_update_dio(struct loop_device *lo)
 			lo->use_dio);
 }
 
+static struct file *loop_real_file(struct file *file)
+{
+	struct file *f = NULL;
+
+	if (file->f_path.dentry->d_sb->s_op->real_loop)
+		f = file->f_path.dentry->d_sb->s_op->real_loop(file);
+	return f;
+}
+
 static void loop_reread_partitions(struct loop_device *lo,
 				   struct block_device *bdev)
 {
@@ -678,6 +687,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
 			  unsigned int arg)
 {
 	struct file	*file = NULL, *old_file;
+	struct file	*f, *virt_file = NULL, *old_virt_file;
 	int		error;
 	bool		partscan;
 
@@ -697,12 +707,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
 	file = fget(arg);
 	if (!file)
 		goto out_err;
+	f = loop_real_file(file);
+	if (f) {
+		virt_file = file;
+		file = f;
+		get_file(file);
+	}
 
 	error = loop_validate_file(file, bdev);
 	if (error)
 		goto out_err;
 
 	old_file = lo->lo_backing_file;
+	old_virt_file = lo->lo_backing_virt_file;
 
 	error = -EINVAL;
 
@@ -714,6 +731,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
 	blk_mq_freeze_queue(lo->lo_queue);
 	mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
 	lo->lo_backing_file = file;
+	lo->lo_backing_virt_file = virt_file;
 	lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
 	mapping_set_gfp_mask(file->f_mapping,
 			     lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
@@ -727,6 +745,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
 	 * dependency.
 	 */
 	fput(old_file);
+	if (old_virt_file)
+		fput(old_virt_file);
 	if (partscan)
 		loop_reread_partitions(lo, bdev);
 	return 0;
@@ -735,6 +755,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
 	mutex_unlock(&loop_ctl_mutex);
 	if (file)
 		fput(file);
+	if (virt_file)
+		fput(virt_file);
 	return error;
 }
 
@@ -939,7 +961,7 @@ static void loop_update_rotational(struct loop_device *lo)
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		       struct block_device *bdev, unsigned int arg)
 {
-	struct file	*file;
+	struct file	*file, *f, *virt_file = NULL;
 	struct inode	*inode;
 	struct address_space *mapping;
 	struct block_device *claimed_bdev = NULL;
@@ -955,6 +977,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 	file = fget(arg);
 	if (!file)
 		goto out;
+	f = loop_real_file(file);
+	if (f) {
+		virt_file = file;
+		file = f;
+		get_file(file);
+	}
 
 	/*
 	 * If we don't hold exclusive handle for the device, upgrade to it
@@ -1003,6 +1031,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 	lo->lo_device = bdev;
 	lo->lo_flags = lo_flags;
 	lo->lo_backing_file = file;
+	lo->lo_backing_virt_file = virt_file;
 	lo->transfer = NULL;
 	lo->ioctl = NULL;
 	lo->lo_sizelimit = 0;
@@ -1056,6 +1085,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		bd_abort_claiming(bdev, claimed_bdev, loop_set_fd);
 out_putf:
 	fput(file);
+	if (virt_file)
+		fput(virt_file);
 out:
 	/* This is safe: open() is still holding a reference. */
 	module_put(THIS_MODULE);
@@ -1102,6 +1133,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
 static int __loop_clr_fd(struct loop_device *lo, bool release)
 {
 	struct file *filp = NULL;
+	struct file *virt_filp = lo->lo_backing_virt_file;
 	gfp_t gfp = lo->old_gfp_mask;
 	struct block_device *bdev = lo->lo_device;
 	int err = 0;
@@ -1125,6 +1157,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
 
 	spin_lock_irq(&lo->lo_lock);
 	lo->lo_backing_file = NULL;
+	lo->lo_backing_virt_file = NULL;
 	spin_unlock_irq(&lo->lo_lock);
 
 	loop_release_xfer(lo);
@@ -1207,6 +1240,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
 	 */
 	if (filp)
 		fput(filp);
+	if (virt_filp)
+		fput(virt_filp);
 	return err;
 }
 
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
J. R. Okajima's avatar
J. R. Okajima committed
143
index af75a5ee4094..1d847cb194ff 100644
J. R. Okajima's avatar
J. R. Okajima committed
144
145
146
147
148
149
150
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -46,7 +46,7 @@ struct loop_device {
 	int		(*ioctl)(struct loop_device *, int cmd, 
 				 unsigned long arg); 
 
-	struct file *	lo_backing_file;
J. R. Okajima's avatar
J. R. Okajima committed
151
+	struct file	*lo_backing_file, *lo_backing_virt_file;
J. R. Okajima's avatar
J. R. Okajima committed
152
153
154
155
 	struct block_device *lo_device;
 	void		*key_data; 
 
diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
J. R. Okajima's avatar
J. R. Okajima committed
156
index 6fb4a4ed8cc7..ba9a959f2db2 100644
J. R. Okajima's avatar
J. R. Okajima committed
157
158
159
160
161
162
163
164
165
166
167
168
--- a/fs/aufs/f_op.c
+++ b/fs/aufs/f_op.c
@@ -359,7 +359,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
 	if (IS_ERR(h_file))
 		goto out;
 
-	if (au_test_loopback_kthread()) {
+	if (0 && au_test_loopback_kthread()) {
 		au_warn_loopback(h_file->f_path.dentry->d_sb);
 		if (file->f_mapping != h_file->f_mapping) {
 			file->f_mapping = h_file->f_mapping;
diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
J. R. Okajima's avatar
J. R. Okajima committed
169
index a8b63acc6204..9d97c3af5686 100644
J. R. Okajima's avatar
J. R. Okajima committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
--- a/fs/aufs/loop.c
+++ b/fs/aufs/loop.c
@@ -133,3 +133,19 @@ void au_loopback_fin(void)
 		symbol_put(loop_backing_file);
 	au_kfree_try_rcu(au_warn_loopback_array);
 }
+
+/* ---------------------------------------------------------------------- */
+
+/* support the loopback block device insude aufs */
+
+struct file *aufs_real_loop(struct file *file)
+{
+	struct file *f;
+
+	BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb));
+	fi_read_lock(file);
+	f = au_hf_top(file);
+	fi_read_unlock(file);
+	AuDebugOn(!f);
+	return f;
+}
diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
J. R. Okajima's avatar
J. R. Okajima committed
193
index 94f4f80ae33b..ca1194354aff 100644
J. R. Okajima's avatar
J. R. Okajima committed
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
--- a/fs/aufs/loop.h
+++ b/fs/aufs/loop.h
@@ -26,6 +26,8 @@ void au_warn_loopback(struct super_block *h_sb);
 
 int au_loopback_init(void);
 void au_loopback_fin(void);
+
+struct file *aufs_real_loop(struct file *file);
 #else
 AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
 
@@ -36,6 +38,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb)
 
 AuStubInt0(au_loopback_init, void)
 AuStubVoid(au_loopback_fin, void)
+
+AuStub(struct file *, aufs_real_loop, return NULL, struct file *file)
 #endif /* BLK_DEV_LOOP */
 
 #endif /* __KERNEL__ */
diff --git a/fs/aufs/super.c b/fs/aufs/super.c
J. R. Okajima's avatar
J. R. Okajima committed
215
index 589dd0122020..801e0a7faec5 100644
J. R. Okajima's avatar
J. R. Okajima committed
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
--- a/fs/aufs/super.c
+++ b/fs/aufs/super.c
@@ -844,7 +844,10 @@ static const struct super_operations aufs_sop = {
 	.statfs		= aufs_statfs,
 	.put_super	= aufs_put_super,
 	.sync_fs	= aufs_sync_fs,
-	.remount_fs	= aufs_remount_fs
+	.remount_fs	= aufs_remount_fs,
+#ifdef CONFIG_AUFS_BDEV_LOOP
+	.real_loop	= aufs_real_loop
+#endif
 };
 
 /* ---------------------------------------------------------------------- */
diff --git a/include/linux/fs.h b/include/linux/fs.h
J. R. Okajima's avatar
J. R. Okajima committed
231
index 381a13995011..215b76e0f9dc 100644
J. R. Okajima's avatar
J. R. Okajima committed
232
233
234
235
236
237
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1973,6 +1973,10 @@ struct super_operations {
 				  struct shrink_control *);
 	long (*free_cached_objects)(struct super_block *,
 				    struct shrink_control *);
J. R. Okajima's avatar
J. R. Okajima committed
238
+#if IS_ENABLED(CONFIG_BLK_DEV_LOOP) || IS_ENABLED(CONFIG_BLK_DEV_LOOP_MODULE)
J. R. Okajima's avatar
J. R. Okajima committed
239
240
241
242
243
244
+	/* and aufs */
+	struct file *(*real_loop)(struct file *);
+#endif
 };
 
 /*