aufs3-loopback.patch 8.09 KB
Newer Older
Manuel's avatar
Manuel committed
1
aufs3.9 loopback patch
2 3

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
Manuel's avatar
Manuel committed
4
index dfe7583..c175e22 100644
5 6
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
Manuel's avatar
Manuel committed
7
@@ -511,7 +511,7 @@ out:
8 9 10 11 12 13 14 15
 }
 
 struct switch_request {
-	struct file *file;
+	struct file *file, *virt_file;
 	struct completion wait;
 };
 
Manuel's avatar
Manuel committed
16
@@ -573,7 +573,8 @@ static int loop_thread(void *data)
17 18 19 20 21 22 23 24 25
  * First it needs to flush existing IO, it does this by sending a magic
  * BIO down the pipe. The completion of this BIO does the actual switch.
  */
-static int loop_switch(struct loop_device *lo, struct file *file)
+static int loop_switch(struct loop_device *lo, struct file *file,
+		       struct file *virt_file)
 {
 	struct switch_request w;
 	struct bio *bio = bio_alloc(GFP_KERNEL, 0);
Manuel's avatar
Manuel committed
26
@@ -581,6 +582,7 @@ static int loop_switch(struct loop_device *lo, struct file *file)
27 28 29 30 31 32 33
 		return -ENOMEM;
 	init_completion(&w.wait);
 	w.file = file;
+	w.virt_file = virt_file;
 	bio->bi_private = &w;
 	bio->bi_bdev = NULL;
 	loop_make_request(lo->lo_queue, bio);
Manuel's avatar
Manuel committed
34
@@ -597,7 +599,7 @@ static int loop_flush(struct loop_device *lo)
35 36 37 38 39 40 41 42
 	if (!lo->lo_thread)
 		return 0;
 
-	return loop_switch(lo, NULL);
+	return loop_switch(lo, NULL, NULL);
 }
 
 /*
Manuel's avatar
Manuel committed
43
@@ -616,6 +618,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
44 45 46 47 48 49 50
 	mapping = file->f_mapping;
 	mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
 	lo->lo_backing_file = file;
+	lo->lo_backing_virt_file = p->virt_file;
 	lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ?
 		mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
 	lo->old_gfp_mask = mapping_gfp_mask(mapping);
Manuel's avatar
Manuel committed
51
@@ -624,6 +627,13 @@ out:
52 53 54 55 56 57 58 59 60 61 62 63 64
 	complete(&p->wait);
 }
 
+static struct file *loop_real_file(struct file *file)
+{
+	struct file *f = NULL;
+	if (file->f_dentry->d_sb->s_op->real_loop)
+		f = file->f_dentry->d_sb->s_op->real_loop(file);
+	return f;
+}
 
 /*
  * loop_change_fd switched the backing store of a loopback device to
Manuel's avatar
Manuel committed
65
@@ -637,6 +647,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
66 67 68 69 70 71 72
 			  unsigned int arg)
 {
 	struct file	*file, *old_file;
+	struct file	*f, *virt_file = NULL, *old_virt_file;
 	struct inode	*inode;
 	int		error;
 
Manuel's avatar
Manuel committed
73
@@ -653,9 +664,16 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
 	file = fget(arg);
 	if (!file)
 		goto out;
+	f = loop_real_file(file);
+	if (f) {
+		virt_file = file;
+		file = f;
+		get_file(file);
+	}
 
 	inode = file->f_mapping->host;
 	old_file = lo->lo_backing_file;
+	old_virt_file = lo->lo_backing_virt_file;
 
 	error = -EINVAL;
 
Manuel's avatar
Manuel committed
90
@@ -667,17 +685,21 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
 		goto out_putf;
 
 	/* and ... switch */
-	error = loop_switch(lo, file);
+	error = loop_switch(lo, file, virt_file);
 	if (error)
 		goto out_putf;
 
 	fput(old_file);
+	if (old_virt_file)
+		fput(old_virt_file);
 	if (lo->lo_flags & LO_FLAGS_PARTSCAN)
 		ioctl_by_bdev(bdev, BLKRRPART, 0);
 	return 0;
 
  out_putf:
 	fput(file);
+	if (virt_file)
+		fput(virt_file);
  out:
 	return error;
 }
Manuel's avatar
Manuel committed
113
@@ -820,7 +842,7 @@ static void loop_config_discard(struct loop_device *lo)
114 115 116 117 118 119 120 121
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		       struct block_device *bdev, unsigned int arg)
 {
-	struct file	*file, *f;
+	struct file	*file, *f, *virt_file = NULL;
 	struct inode	*inode;
 	struct address_space *mapping;
 	unsigned lo_blocksize;
Manuel's avatar
Manuel committed
122
@@ -835,6 +857,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
123 124 125 126 127 128 129 130 131 132 133 134
 	file = fget(arg);
 	if (!file)
 		goto out;
+	f = loop_real_file(file);
+	if (f) {
+		virt_file = file;
+		file = f;
+		get_file(file);
+	}
 
 	error = -EBUSY;
 	if (lo->lo_state != Lo_unbound)
Manuel's avatar
Manuel committed
135
@@ -883,6 +911,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
136 137 138 139 140 141 142
 	lo->lo_device = bdev;
 	lo->lo_flags = lo_flags;
 	lo->lo_backing_file = file;
+	lo->lo_backing_virt_file = virt_file;
 	lo->transfer = transfer_none;
 	lo->ioctl = NULL;
 	lo->lo_sizelimit = 0;
Manuel's avatar
Manuel committed
143
@@ -934,6 +963,7 @@ out_clr:
144 145 146 147 148 149 150
 	lo->lo_thread = NULL;
 	lo->lo_device = NULL;
 	lo->lo_backing_file = NULL;
+	lo->lo_backing_virt_file = NULL;
 	lo->lo_flags = 0;
 	set_capacity(lo->lo_disk, 0);
 	invalidate_bdev(bdev);
Manuel's avatar
Manuel committed
151
@@ -943,6 +973,8 @@ out_clr:
152 153 154 155 156 157 158 159
 	lo->lo_state = Lo_unbound;
  out_putf:
 	fput(file);
+	if (virt_file)
+		fput(virt_file);
  out:
 	/* This is safe: open() is still holding a reference. */
 	module_put(THIS_MODULE);
Manuel's avatar
Manuel committed
160
@@ -989,6 +1021,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
161 162 163 164 165 166 167
 static int loop_clr_fd(struct loop_device *lo)
 {
 	struct file *filp = lo->lo_backing_file;
+	struct file *virt_filp = lo->lo_backing_virt_file;
 	gfp_t gfp = lo->old_gfp_mask;
 	struct block_device *bdev = lo->lo_device;
 
Manuel's avatar
Manuel committed
168
@@ -1022,6 +1055,7 @@ static int loop_clr_fd(struct loop_device *lo)
169 170 171 172 173 174 175
 
 	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);
Manuel's avatar
Manuel committed
176
@@ -1064,6 +1098,8 @@ static int loop_clr_fd(struct loop_device *lo)
177 178 179 180 181 182 183 184 185
 	 * bd_mutex which is usually taken before lo_ctl_mutex.
 	 */
 	fput(filp);
+	if (virt_filp)
+		fput(virt_filp);
 	return 0;
 }
 
diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
Manuel's avatar
Manuel committed
186
index 56924c5..b832bf8 100644
187 188
--- a/fs/aufs/f_op.c
+++ b/fs/aufs/f_op.c
189
@@ -352,7 +352,7 @@ static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
190 191 192 193 194 195 196 197 198
 	err = -EINVAL;
 	h_file = au_hf_top(file);
 	get_file(h_file);
-	if (au_test_loopback_kthread()) {
+	if (0 && au_test_loopback_kthread()) {
 		au_warn_loopback(h_file->f_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
Manuel's avatar
Manuel committed
199
index ccae19c..15dc5c2 100644
200 201
--- a/fs/aufs/loop.c
+++ b/fs/aufs/loop.c
Manuel's avatar
Manuel committed
202
@@ -133,3 +133,19 @@ void au_loopback_fin(void)
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
 {
 	kfree(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_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
abveritas's avatar
abveritas committed
223
index 88d019c..8707c3a 100644
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
--- a/fs/aufs/loop.h
+++ b/fs/aufs/loop.h
@@ -36,6 +36,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
 AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
 	   struct dentry *h_adding)
@@ -44,6 +46,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
Manuel's avatar
Manuel committed
245
index 4f57ba0..786ffea 100644
246 247
--- a/fs/aufs/super.c
+++ b/fs/aufs/super.c
abveritas's avatar
abveritas committed
248
@@ -811,7 +811,10 @@ static const struct super_operations aufs_sop = {
249 250
 	.statfs		= aufs_statfs,
 	.put_super	= aufs_put_super,
abveritas's avatar
abveritas committed
251
 	.sync_fs	= aufs_sync_fs,
252 253 254 255 256 257 258 259 260
-	.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
Manuel's avatar
Manuel committed
261
index 5c49108..f8e9fd4 100644
262 263
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
Manuel's avatar
Manuel committed
264
@@ -1614,6 +1614,10 @@ struct super_operations {
265 266 267 268 269 270 271 272 273 274 275
 	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
 	int (*nr_cached_objects)(struct super_block *);
 	void (*free_cached_objects)(struct super_block *, int);
+#if defined(CONFIG_BLK_DEV_LOOP) ||  defined(CONFIG_BLK_DEV_LOOP_MODULE)
+	/* and aufs */
+	struct file *(*real_loop)(struct file *);
+#endif
 };
 
 /*
diff --git a/include/linux/loop.h b/include/linux/loop.h
Manuel's avatar
Manuel committed
276
index 460b60f..6910d80 100644
277 278
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
abveritas's avatar
abveritas committed
279
@@ -44,7 +44,7 @@ struct loop_device {
280 281 282 283 284 285 286 287
 	int		(*ioctl)(struct loop_device *, int cmd, 
 				 unsigned long arg); 
 
-	struct file *	lo_backing_file;
+	struct file *	lo_backing_file, *lo_backing_virt_file;
 	struct block_device *lo_device;
 	unsigned	lo_blocksize;
 	void		*key_data;