rev |
line source |
pascal@24141
|
1 aufs3.16 loopback patch
|
pascal@24141
|
2
|
pascal@24141
|
3 diff --git a/drivers/block/loop.c b/drivers/block/loop.c
|
pascal@24141
|
4 index 30efd68..77b31b4 100644
|
pascal@24141
|
5 --- a/drivers/block/loop.c
|
pascal@24141
|
6 +++ b/drivers/block/loop.c
|
pascal@24141
|
7 @@ -514,7 +514,7 @@ out:
|
pascal@24141
|
8 }
|
pascal@24141
|
9
|
pascal@24141
|
10 struct switch_request {
|
pascal@24141
|
11 - struct file *file;
|
pascal@24141
|
12 + struct file *file, *virt_file;
|
pascal@24141
|
13 struct completion wait;
|
pascal@24141
|
14 };
|
pascal@24141
|
15
|
pascal@24141
|
16 @@ -576,7 +576,8 @@ static int loop_thread(void *data)
|
pascal@24141
|
17 * First it needs to flush existing IO, it does this by sending a magic
|
pascal@24141
|
18 * BIO down the pipe. The completion of this BIO does the actual switch.
|
pascal@24141
|
19 */
|
pascal@24141
|
20 -static int loop_switch(struct loop_device *lo, struct file *file)
|
pascal@24141
|
21 +static int loop_switch(struct loop_device *lo, struct file *file,
|
pascal@24141
|
22 + struct file *virt_file)
|
pascal@24141
|
23 {
|
pascal@24141
|
24 struct switch_request w;
|
pascal@24141
|
25 struct bio *bio = bio_alloc(GFP_KERNEL, 0);
|
pascal@24141
|
26 @@ -584,6 +585,7 @@ static int loop_switch(struct loop_device *lo, struct file *file)
|
pascal@24141
|
27 return -ENOMEM;
|
pascal@24141
|
28 init_completion(&w.wait);
|
pascal@24141
|
29 w.file = file;
|
pascal@24141
|
30 + w.virt_file = virt_file;
|
pascal@24141
|
31 bio->bi_private = &w;
|
pascal@24141
|
32 bio->bi_bdev = NULL;
|
pascal@24141
|
33 loop_make_request(lo->lo_queue, bio);
|
pascal@24141
|
34 @@ -600,7 +602,7 @@ static int loop_flush(struct loop_device *lo)
|
pascal@24141
|
35 if (!lo->lo_thread)
|
pascal@24141
|
36 return 0;
|
pascal@24141
|
37
|
pascal@24141
|
38 - return loop_switch(lo, NULL);
|
pascal@24141
|
39 + return loop_switch(lo, NULL, NULL);
|
pascal@24141
|
40 }
|
pascal@24141
|
41
|
pascal@24141
|
42 /*
|
pascal@24141
|
43 @@ -619,6 +621,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
|
pascal@24141
|
44 mapping = file->f_mapping;
|
pascal@24141
|
45 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
|
pascal@24141
|
46 lo->lo_backing_file = file;
|
pascal@24141
|
47 + lo->lo_backing_virt_file = p->virt_file;
|
pascal@24141
|
48 lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ?
|
pascal@24141
|
49 mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
|
pascal@24141
|
50 lo->old_gfp_mask = mapping_gfp_mask(mapping);
|
pascal@24141
|
51 @@ -627,6 +630,13 @@ out:
|
pascal@24141
|
52 complete(&p->wait);
|
pascal@24141
|
53 }
|
pascal@24141
|
54
|
pascal@24141
|
55 +static struct file *loop_real_file(struct file *file)
|
pascal@24141
|
56 +{
|
pascal@24141
|
57 + struct file *f = NULL;
|
pascal@24141
|
58 + if (file->f_dentry->d_sb->s_op->real_loop)
|
pascal@24141
|
59 + f = file->f_dentry->d_sb->s_op->real_loop(file);
|
pascal@24141
|
60 + return f;
|
pascal@24141
|
61 +}
|
pascal@24141
|
62
|
pascal@24141
|
63 /*
|
pascal@24141
|
64 * loop_change_fd switched the backing store of a loopback device to
|
pascal@24141
|
65 @@ -640,6 +650,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
|
pascal@24141
|
66 unsigned int arg)
|
pascal@24141
|
67 {
|
pascal@24141
|
68 struct file *file, *old_file;
|
pascal@24141
|
69 + struct file *f, *virt_file = NULL, *old_virt_file;
|
pascal@24141
|
70 struct inode *inode;
|
pascal@24141
|
71 int error;
|
pascal@24141
|
72
|
pascal@24141
|
73 @@ -656,9 +667,16 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
|
pascal@24141
|
74 file = fget(arg);
|
pascal@24141
|
75 if (!file)
|
pascal@24141
|
76 goto out;
|
pascal@24141
|
77 + f = loop_real_file(file);
|
pascal@24141
|
78 + if (f) {
|
pascal@24141
|
79 + virt_file = file;
|
pascal@24141
|
80 + file = f;
|
pascal@24141
|
81 + get_file(file);
|
pascal@24141
|
82 + }
|
pascal@24141
|
83
|
pascal@24141
|
84 inode = file->f_mapping->host;
|
pascal@24141
|
85 old_file = lo->lo_backing_file;
|
pascal@24141
|
86 + old_virt_file = lo->lo_backing_virt_file;
|
pascal@24141
|
87
|
pascal@24141
|
88 error = -EINVAL;
|
pascal@24141
|
89
|
pascal@24141
|
90 @@ -670,17 +688,21 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
|
pascal@24141
|
91 goto out_putf;
|
pascal@24141
|
92
|
pascal@24141
|
93 /* and ... switch */
|
pascal@24141
|
94 - error = loop_switch(lo, file);
|
pascal@24141
|
95 + error = loop_switch(lo, file, virt_file);
|
pascal@24141
|
96 if (error)
|
pascal@24141
|
97 goto out_putf;
|
pascal@24141
|
98
|
pascal@24141
|
99 fput(old_file);
|
pascal@24141
|
100 + if (old_virt_file)
|
pascal@24141
|
101 + fput(old_virt_file);
|
pascal@24141
|
102 if (lo->lo_flags & LO_FLAGS_PARTSCAN)
|
pascal@24141
|
103 ioctl_by_bdev(bdev, BLKRRPART, 0);
|
pascal@24141
|
104 return 0;
|
pascal@24141
|
105
|
pascal@24141
|
106 out_putf:
|
pascal@24141
|
107 fput(file);
|
pascal@24141
|
108 + if (virt_file)
|
pascal@24141
|
109 + fput(virt_file);
|
pascal@24141
|
110 out:
|
pascal@24141
|
111 return error;
|
pascal@24141
|
112 }
|
pascal@24141
|
113 @@ -841,7 +863,7 @@ static void loop_config_discard(struct loop_device *lo)
|
pascal@24141
|
114 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
|
pascal@24141
|
115 struct block_device *bdev, unsigned int arg)
|
pascal@24141
|
116 {
|
pascal@24141
|
117 - struct file *file, *f;
|
pascal@24141
|
118 + struct file *file, *f, *virt_file = NULL;
|
pascal@24141
|
119 struct inode *inode;
|
pascal@24141
|
120 struct address_space *mapping;
|
pascal@24141
|
121 unsigned lo_blocksize;
|
pascal@24141
|
122 @@ -856,6 +878,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
|
pascal@24141
|
123 file = fget(arg);
|
pascal@24141
|
124 if (!file)
|
pascal@24141
|
125 goto out;
|
pascal@24141
|
126 + f = loop_real_file(file);
|
pascal@24141
|
127 + if (f) {
|
pascal@24141
|
128 + virt_file = file;
|
pascal@24141
|
129 + file = f;
|
pascal@24141
|
130 + get_file(file);
|
pascal@24141
|
131 + }
|
pascal@24141
|
132
|
pascal@24141
|
133 error = -EBUSY;
|
pascal@24141
|
134 if (lo->lo_state != Lo_unbound)
|
pascal@24141
|
135 @@ -904,6 +932,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
|
pascal@24141
|
136 lo->lo_device = bdev;
|
pascal@24141
|
137 lo->lo_flags = lo_flags;
|
pascal@24141
|
138 lo->lo_backing_file = file;
|
pascal@24141
|
139 + lo->lo_backing_virt_file = virt_file;
|
pascal@24141
|
140 lo->transfer = transfer_none;
|
pascal@24141
|
141 lo->ioctl = NULL;
|
pascal@24141
|
142 lo->lo_sizelimit = 0;
|
pascal@24141
|
143 @@ -948,6 +977,7 @@ out_clr:
|
pascal@24141
|
144 lo->lo_thread = NULL;
|
pascal@24141
|
145 lo->lo_device = NULL;
|
pascal@24141
|
146 lo->lo_backing_file = NULL;
|
pascal@24141
|
147 + lo->lo_backing_virt_file = NULL;
|
pascal@24141
|
148 lo->lo_flags = 0;
|
pascal@24141
|
149 set_capacity(lo->lo_disk, 0);
|
pascal@24141
|
150 invalidate_bdev(bdev);
|
pascal@24141
|
151 @@ -957,6 +987,8 @@ out_clr:
|
pascal@24141
|
152 lo->lo_state = Lo_unbound;
|
pascal@24141
|
153 out_putf:
|
pascal@24141
|
154 fput(file);
|
pascal@24141
|
155 + if (virt_file)
|
pascal@24141
|
156 + fput(virt_file);
|
pascal@24141
|
157 out:
|
pascal@24141
|
158 /* This is safe: open() is still holding a reference. */
|
pascal@24141
|
159 module_put(THIS_MODULE);
|
pascal@24141
|
160 @@ -1003,6 +1035,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
|
pascal@24141
|
161 static int loop_clr_fd(struct loop_device *lo)
|
pascal@24141
|
162 {
|
pascal@24141
|
163 struct file *filp = lo->lo_backing_file;
|
pascal@24141
|
164 + struct file *virt_filp = lo->lo_backing_virt_file;
|
pascal@24141
|
165 gfp_t gfp = lo->old_gfp_mask;
|
pascal@24141
|
166 struct block_device *bdev = lo->lo_device;
|
pascal@24141
|
167
|
pascal@24141
|
168 @@ -1036,6 +1069,7 @@ static int loop_clr_fd(struct loop_device *lo)
|
pascal@24141
|
169
|
pascal@24141
|
170 spin_lock_irq(&lo->lo_lock);
|
pascal@24141
|
171 lo->lo_backing_file = NULL;
|
pascal@24141
|
172 + lo->lo_backing_virt_file = NULL;
|
pascal@24141
|
173 spin_unlock_irq(&lo->lo_lock);
|
pascal@24141
|
174
|
pascal@24141
|
175 loop_release_xfer(lo);
|
pascal@24141
|
176 @@ -1078,6 +1112,8 @@ static int loop_clr_fd(struct loop_device *lo)
|
pascal@24141
|
177 * bd_mutex which is usually taken before lo_ctl_mutex.
|
pascal@24141
|
178 */
|
pascal@24141
|
179 fput(filp);
|
pascal@24141
|
180 + if (virt_filp)
|
pascal@24141
|
181 + fput(virt_filp);
|
pascal@24141
|
182 return 0;
|
pascal@24141
|
183 }
|
pascal@24141
|
184
|
pascal@24141
|
185 diff --git a/drivers/block/loop.h b/drivers/block/loop.h
|
pascal@24141
|
186 index 90df5d6..cb91822 100644
|
pascal@24141
|
187 --- a/drivers/block/loop.h
|
pascal@24141
|
188 +++ b/drivers/block/loop.h
|
pascal@24141
|
189 @@ -44,7 +44,7 @@ struct loop_device {
|
pascal@24141
|
190 int (*ioctl)(struct loop_device *, int cmd,
|
pascal@24141
|
191 unsigned long arg);
|
pascal@24141
|
192
|
pascal@24141
|
193 - struct file * lo_backing_file;
|
pascal@24141
|
194 + struct file * lo_backing_file, *lo_backing_virt_file;
|
pascal@24141
|
195 struct block_device *lo_device;
|
pascal@24141
|
196 unsigned lo_blocksize;
|
pascal@24141
|
197 void *key_data;
|
pascal@24141
|
198 diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
|
pascal@24141
|
199 index 95ff59f..79cc7b6 100644
|
pascal@24141
|
200 --- a/fs/aufs/f_op.c
|
pascal@24141
|
201 +++ b/fs/aufs/f_op.c
|
pascal@24141
|
202 @@ -398,7 +398,7 @@ static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
|
pascal@24141
|
203 if (IS_ERR(h_file))
|
pascal@24141
|
204 goto out;
|
pascal@24141
|
205
|
pascal@24141
|
206 - if (au_test_loopback_kthread()) {
|
pascal@24141
|
207 + if (0 && au_test_loopback_kthread()) {
|
pascal@24141
|
208 au_warn_loopback(h_file->f_dentry->d_sb);
|
pascal@24141
|
209 if (file->f_mapping != h_file->f_mapping) {
|
pascal@24141
|
210 file->f_mapping = h_file->f_mapping;
|
pascal@24141
|
211 diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
|
pascal@24141
|
212 index 2a3e245..e2ac602 100644
|
pascal@24141
|
213 --- a/fs/aufs/loop.c
|
pascal@24141
|
214 +++ b/fs/aufs/loop.c
|
pascal@24141
|
215 @@ -130,3 +130,19 @@ void au_loopback_fin(void)
|
pascal@24141
|
216 symbol_put(loop_backing_file);
|
pascal@24141
|
217 kfree(au_warn_loopback_array);
|
pascal@24141
|
218 }
|
pascal@24141
|
219 +
|
pascal@24141
|
220 +/* ---------------------------------------------------------------------- */
|
pascal@24141
|
221 +
|
pascal@24141
|
222 +/* support the loopback block device insude aufs */
|
pascal@24141
|
223 +
|
pascal@24141
|
224 +struct file *aufs_real_loop(struct file *file)
|
pascal@24141
|
225 +{
|
pascal@24141
|
226 + struct file *f;
|
pascal@24141
|
227 +
|
pascal@24141
|
228 + BUG_ON(!au_test_aufs(file->f_dentry->d_sb));
|
pascal@24141
|
229 + fi_read_lock(file);
|
pascal@24141
|
230 + f = au_hf_top(file);
|
pascal@24141
|
231 + fi_read_unlock(file);
|
pascal@24141
|
232 + AuDebugOn(!f);
|
pascal@24141
|
233 + return f;
|
pascal@24141
|
234 +}
|
pascal@24141
|
235 diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
|
pascal@24141
|
236 index 6d9864d..3322557 100644
|
pascal@24141
|
237 --- a/fs/aufs/loop.h
|
pascal@24141
|
238 +++ b/fs/aufs/loop.h
|
pascal@24141
|
239 @@ -25,7 +25,11 @@ void au_warn_loopback(struct super_block *h_sb);
|
pascal@24141
|
240
|
pascal@24141
|
241 int au_loopback_init(void);
|
pascal@24141
|
242 void au_loopback_fin(void);
|
pascal@24141
|
243 +
|
pascal@24141
|
244 +struct file *aufs_real_loop(struct file *file);
|
pascal@24141
|
245 #else
|
pascal@24141
|
246 +AuStub(struct file *, loop_backing_file, return NULL)
|
pascal@24141
|
247 +
|
pascal@24141
|
248 AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
|
pascal@24141
|
249 struct dentry *h_adding)
|
pascal@24141
|
250 AuStubInt0(au_test_loopback_kthread, void)
|
pascal@24141
|
251 @@ -33,6 +37,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb)
|
pascal@24141
|
252
|
pascal@24141
|
253 AuStubInt0(au_loopback_init, void)
|
pascal@24141
|
254 AuStubVoid(au_loopback_fin, void)
|
pascal@24141
|
255 +
|
pascal@24141
|
256 +AuStub(struct file *, aufs_real_loop, return NULL, struct file *file)
|
pascal@24141
|
257 #endif /* BLK_DEV_LOOP */
|
pascal@24141
|
258
|
pascal@24141
|
259 #endif /* __KERNEL__ */
|
pascal@24141
|
260 diff --git a/fs/aufs/super.c b/fs/aufs/super.c
|
pascal@24141
|
261 index 52ee100..bd545df 100644
|
pascal@24141
|
262 --- a/fs/aufs/super.c
|
pascal@24141
|
263 +++ b/fs/aufs/super.c
|
pascal@24141
|
264 @@ -810,7 +810,10 @@ static const struct super_operations aufs_sop = {
|
pascal@24141
|
265 .statfs = aufs_statfs,
|
pascal@24141
|
266 .put_super = aufs_put_super,
|
pascal@24141
|
267 .sync_fs = aufs_sync_fs,
|
pascal@24141
|
268 - .remount_fs = aufs_remount_fs
|
pascal@24141
|
269 + .remount_fs = aufs_remount_fs,
|
pascal@24141
|
270 +#ifdef CONFIG_AUFS_BDEV_LOOP
|
pascal@24141
|
271 + .real_loop = aufs_real_loop
|
pascal@24141
|
272 +#endif
|
pascal@24141
|
273 };
|
pascal@24141
|
274
|
pascal@24141
|
275 /* ---------------------------------------------------------------------- */
|
pascal@24141
|
276 diff --git a/include/linux/fs.h b/include/linux/fs.h
|
pascal@24141
|
277 index 2f32b35..f94f0e6 100644
|
pascal@24141
|
278 --- a/include/linux/fs.h
|
pascal@24141
|
279 +++ b/include/linux/fs.h
|
pascal@24141
|
280 @@ -1561,6 +1561,10 @@ struct super_operations {
|
pascal@24141
|
281 int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
|
pascal@24141
|
282 long (*nr_cached_objects)(struct super_block *, int);
|
pascal@24141
|
283 long (*free_cached_objects)(struct super_block *, long, int);
|
pascal@24141
|
284 +#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
|
pascal@24141
|
285 + /* and aufs */
|
pascal@24141
|
286 + struct file *(*real_loop)(struct file *);
|
pascal@24141
|
287 +#endif
|
pascal@24141
|
288 };
|
pascal@24141
|
289
|
pascal@24141
|
290 /*
|