+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags);
#endif
-aufs3.14 loopback patch
-
-diff --git a/drivers/block/loop.c b/drivers/block/loop.c
-index ec278ac..1894990 100644
---- a/drivers/block/loop.c
-+++ b/drivers/block/loop.c
-@@ -514,7 +514,7 @@ out:
- }
-
- struct switch_request {
-- struct file *file;
-+ struct file *file, *virt_file;
- struct completion wait;
- };
-
-@@ -576,7 +576,8 @@ static int loop_thread(void *data)
- * 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);
-@@ -584,6 +585,7 @@ static int loop_switch(struct loop_device *lo, struct file *file)
- 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);
-@@ -600,7 +602,7 @@ static int loop_flush(struct loop_device *lo)
- if (!lo->lo_thread)
- return 0;
-
-- return loop_switch(lo, NULL);
-+ return loop_switch(lo, NULL, NULL);
- }
-
- /*
-@@ -619,6 +621,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
- 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);
-@@ -627,6 +630,13 @@ out:
- 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
-@@ -640,6 +650,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
- unsigned int arg)
- {
- struct file *file, *old_file;
-+ struct file *f, *virt_file = NULL, *old_virt_file;
- struct inode *inode;
- int error;
-
-@@ -656,9 +667,16 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
- 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;
-
-@@ -670,17 +688,21 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
- 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;
- }
-@@ -841,7 +863,7 @@ static void loop_config_discard(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, *f;
-+ struct file *file, *f, *virt_file = NULL;
- struct inode *inode;
- struct address_space *mapping;
- unsigned lo_blocksize;
-@@ -856,6 +878,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);
-+ }
-
- error = -EBUSY;
- if (lo->lo_state != Lo_unbound)
-@@ -904,6 +932,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 = transfer_none;
- lo->ioctl = NULL;
- lo->lo_sizelimit = 0;
-@@ -948,6 +977,7 @@ out_clr:
- 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);
-@@ -957,6 +987,8 @@ out_clr:
- 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);
-@@ -1003,6 +1035,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
- 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;
-
-@@ -1036,6 +1069,7 @@ static int loop_clr_fd(struct loop_device *lo)
-
- 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);
-@@ -1078,6 +1112,8 @@ static int loop_clr_fd(struct loop_device *lo)
- * bd_mutex which is usually taken before lo_ctl_mutex.
- */
- fput(filp);
-+ if (virt_filp)
-+ fput(virt_filp);
- return 0;
- }
-
-diff --git a/drivers/block/loop.h b/drivers/block/loop.h
-index 90df5d6..cb91822 100644
---- a/drivers/block/loop.h
-+++ b/drivers/block/loop.h
-@@ -44,7 +44,7 @@ struct loop_device {
- 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;
-diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
-index 2e0302d..b35af58 100644
---- a/fs/aufs/f_op.c
-+++ b/fs/aufs/f_op.c
-@@ -337,7 +337,7 @@ static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
- 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
-index 3b03b52..4ab749d 100644
---- a/fs/aufs/loop.c
-+++ b/fs/aufs/loop.c
-@@ -130,3 +130,19 @@ void au_loopback_fin(void)
- symbol_put(loop_backing_file);
- 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
-index da8b756..28cb7ea 100644
---- a/fs/aufs/loop.h
-+++ b/fs/aufs/loop.h
-@@ -25,7 +25,11 @@ 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)
-+
- AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
- struct dentry *h_adding)
- AuStubInt0(au_test_loopback_kthread, void)
-@@ -33,6 +37,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
-index b609e5a..e3909ed 100644
---- a/fs/aufs/super.c
-+++ b/fs/aufs/super.c
-@@ -807,7 +807,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
-index f3f635c..c4308ca 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -1626,6 +1626,10 @@ struct super_operations {
- int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
- long (*nr_cached_objects)(struct super_block *, int);
- long (*free_cached_objects)(struct super_block *, long, int);
-+#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
-+ /* and aufs */
-+ struct file *(*real_loop)(struct file *);
-+#endif
- };
-
- /*
aufs3.14 mmap patch
diff --git a/fs/buffer.c b/fs/buffer.c
+ struct aufs_mvdown)
+
+#endif /* __AUFS_TYPE_H__ */
+aufs3.14 loopback patch
+
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index ec278ac..1894990 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -514,7 +514,7 @@ out:
+ }
+
+ struct switch_request {
+- struct file *file;
++ struct file *file, *virt_file;
+ struct completion wait;
+ };
+
+@@ -576,7 +576,8 @@ static int loop_thread(void *data)
+ * 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);
+@@ -584,6 +585,7 @@ static int loop_switch(struct loop_device *lo, struct file *file)
+ 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);
+@@ -600,7 +602,7 @@ static int loop_flush(struct loop_device *lo)
+ if (!lo->lo_thread)
+ return 0;
+
+- return loop_switch(lo, NULL);
++ return loop_switch(lo, NULL, NULL);
+ }
+
+ /*
+@@ -619,6 +621,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
+ 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);
+@@ -627,6 +630,13 @@ out:
+ 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
+@@ -640,6 +650,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
+ unsigned int arg)
+ {
+ struct file *file, *old_file;
++ struct file *f, *virt_file = NULL, *old_virt_file;
+ struct inode *inode;
+ int error;
+
+@@ -656,9 +667,16 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
+ 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;
+
+@@ -670,17 +688,21 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
+ 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;
+ }
+@@ -841,7 +863,7 @@ static void loop_config_discard(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, *f;
++ struct file *file, *f, *virt_file = NULL;
+ struct inode *inode;
+ struct address_space *mapping;
+ unsigned lo_blocksize;
+@@ -856,6 +878,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);
++ }
+
+ error = -EBUSY;
+ if (lo->lo_state != Lo_unbound)
+@@ -904,6 +932,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 = transfer_none;
+ lo->ioctl = NULL;
+ lo->lo_sizelimit = 0;
+@@ -948,6 +977,7 @@ out_clr:
+ 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);
+@@ -957,6 +987,8 @@ out_clr:
+ 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);
+@@ -1003,6 +1035,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
+ 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;
+
+@@ -1036,6 +1069,7 @@ static int loop_clr_fd(struct loop_device *lo)
+
+ 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);
+@@ -1078,6 +1112,8 @@ static int loop_clr_fd(struct loop_device *lo)
+ * bd_mutex which is usually taken before lo_ctl_mutex.
+ */
+ fput(filp);
++ if (virt_filp)
++ fput(virt_filp);
+ return 0;
+ }
+
+diff --git a/drivers/block/loop.h b/drivers/block/loop.h
+index 90df5d6..cb91822 100644
+--- a/drivers/block/loop.h
++++ b/drivers/block/loop.h
+@@ -44,7 +44,7 @@ struct loop_device {
+ 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;
+diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
+index 2e0302d..b35af58 100644
+--- a/fs/aufs/f_op.c
++++ b/fs/aufs/f_op.c
+@@ -337,7 +337,7 @@ static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
+ 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
+index 3b03b52..4ab749d 100644
+--- a/fs/aufs/loop.c
++++ b/fs/aufs/loop.c
+@@ -130,3 +130,19 @@ void au_loopback_fin(void)
+ symbol_put(loop_backing_file);
+ 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
+index da8b756..28cb7ea 100644
+--- a/fs/aufs/loop.h
++++ b/fs/aufs/loop.h
+@@ -25,7 +25,11 @@ 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)
++
+ AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
+ struct dentry *h_adding)
+ AuStubInt0(au_test_loopback_kthread, void)
+@@ -33,6 +37,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
+index b609e5a..e3909ed 100644
+--- a/fs/aufs/super.c
++++ b/fs/aufs/super.c
+@@ -807,7 +807,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
+index f3f635c..c4308ca 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1626,6 +1626,10 @@ struct super_operations {
+ int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+ long (*nr_cached_objects)(struct super_block *, int);
+ long (*free_cached_objects)(struct super_block *, long, int);
++#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
++ /* and aufs */
++ struct file *(*real_loop)(struct file *);
++#endif
+ };
+
+ /*