Hi,

I see from the mailing list you are pausing development for a short while
and do not expect to be releasing v4.2 based patches in the early cycle.
As Ubuntu is currently moving upwards onto those kernels activly we have
gone ahead and done some porting work on aufs4 for that.  I am enclosing
the updates and patches we have made in the hope they are some help when
you return, and of help to others.

Attached are updated versions of the following patches:

        aufs4-standalone.patch
        aufs4-loopback.patch

Plus a porting patch to the new readlink()/putlink() VFS API.

I should note that these have had very very little testing beyond smoke
testing so there may be issues or further updates yet.

Cheers.

-apw
>From 8882bf3cc1378c13c714065a9445037cf29b44eb Mon Sep 17 00:00:00 2001
From: Andy Whitcroft <a...@canonical.com>
Date: Thu, 30 Jul 2015 13:19:02 +0100
Subject: [PATCH] UBUNTU: aufs4: aufs4-standalone.patch

Signed-off-by: Andy Whitcroft <a...@canonical.com>
---
 fs/dcache.c              |  1 +
 fs/file_table.c          |  2 ++
 fs/inode.c               |  1 +
 fs/namespace.c           |  2 ++
 fs/notify/group.c        |  4 ++++
 fs/notify/mark.c         |  4 ++++
 fs/open.c                |  2 ++
 fs/read_write.c          |  2 ++
 fs/splice.c              |  2 ++
 fs/xattr.c               |  1 +
 security/commoncap.c     |  2 ++
 security/device_cgroup.c |  2 ++
 security/security.c      | 10 ++++++++++
 13 files changed, 35 insertions(+)

diff --git a/fs/dcache.c b/fs/dcache.c
index 0a6f203..082440c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1272,6 +1272,7 @@ rename_retry:
 	seq = 1;
 	goto again;
 }
+EXPORT_SYMBOL(d_walk);
 
 /*
  * Search for at least 1 mount point in the dentry's subdirs.
diff --git a/fs/file_table.c b/fs/file_table.c
index 7f9d407..8c9ec1d 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -146,6 +146,7 @@ over:
 	}
 	return ERR_PTR(-ENFILE);
 }
+EXPORT_SYMBOL(get_empty_filp);
 
 /**
  * alloc_file - allocate and initialize a 'struct file'
@@ -307,6 +308,7 @@ void put_filp(struct file *file)
 		file_free(file);
 	}
 }
+EXPORT_SYMBOL(put_filp);
 
 void __init files_init(unsigned long mempages)
 { 
diff --git a/fs/inode.c b/fs/inode.c
index d30640f..1ecc715 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -58,6 +58,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock);
 
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock);
+EXPORT_SYMBOL(inode_sb_list_lock);
 
 /*
  * Empty aops. Can be used for the cases where the user does not
diff --git a/fs/namespace.c b/fs/namespace.c
index 2b8aa15..2caee44 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -463,6 +463,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
 	mnt_dec_writers(real_mount(mnt));
 	preempt_enable();
 }
+EXPORT_SYMBOL_GPL(__mnt_drop_write);
 
 /**
  * mnt_drop_write - give up write access to a mount
@@ -1803,6 +1804,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
 	}
 	return 0;
 }
+EXPORT_SYMBOL(iterate_mounts);
 
 static void cleanup_group_ids(struct mount *mnt, struct mount *end)
 {
diff --git a/fs/notify/group.c b/fs/notify/group.c
index d16b62c..06ca6bc 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -22,6 +22,7 @@
 #include <linux/srcu.h>
 #include <linux/rculist.h>
 #include <linux/wait.h>
+#include <linux/module.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
@@ -72,6 +73,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
 {
 	atomic_inc(&group->refcnt);
 }
+EXPORT_SYMBOL(fsnotify_get_group);
 
 /*
  * Drop a reference to a group.  Free it if it's through.
@@ -81,6 +83,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
 	if (atomic_dec_and_test(&group->refcnt))
 		fsnotify_final_destroy_group(group);
 }
+EXPORT_SYMBOL(fsnotify_put_group);
 
 /*
  * Create a new fsnotify_group and hold a reference for the group returned.
@@ -109,6 +112,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 
 	return group;
 }
+EXPORT_SYMBOL(fsnotify_alloc_group);
 
 int fsnotify_fasync(int fd, struct file *file, int on)
 {
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 92e48c7..92353ee 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -109,6 +109,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
 		mark->free_mark(mark);
 	}
 }
+EXPORT_SYMBOL(fsnotify_put_mark);
 
 /* Calculate mask of events for a list of marks */
 u32 fsnotify_recalc_mask(struct hlist_head *head)
@@ -202,6 +203,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark,
 	fsnotify_destroy_mark_locked(mark, group);
 	mutex_unlock(&group->mark_mutex);
 }
+EXPORT_SYMBOL(fsnotify_destroy_mark);
 
 /*
  * Destroy all marks in the given list. The marks must be already detached from
@@ -386,6 +388,7 @@ int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
 	mutex_unlock(&group->mark_mutex);
 	return ret;
 }
+EXPORT_SYMBOL(fsnotify_add_mark);
 
 /*
  * Given a list of marks, find the mark associated with given group. If found
@@ -455,6 +458,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
 	atomic_set(&mark->refcnt, 1);
 	mark->free_mark = free_mark;
 }
+EXPORT_SYMBOL(fsnotify_init_mark);
 
 static int fsnotify_mark_destroy(void *ignored)
 {
diff --git a/fs/open.c b/fs/open.c
index e09950b..d2d9344 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -67,6 +67,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 	mutex_unlock(&dentry->d_inode->i_mutex);
 	return ret;
 }
+EXPORT_SYMBOL(do_truncate);
 
 long vfs_truncate(struct path *path, loff_t length)
 {
@@ -681,6 +682,7 @@ int open_check_o_direct(struct file *f)
 	}
 	return 0;
 }
+EXPORT_SYMBOL(open_check_o_direct);
 
 static int do_dentry_open(struct file *f,
 			  struct inode *inode,
diff --git a/fs/read_write.c b/fs/read_write.c
index fd0414e..8ace6ec 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -504,6 +504,7 @@ vfs_readf_t vfs_readf(struct file *file)
 		return new_sync_read;
 	return ERR_PTR(-ENOSYS);
 }
+EXPORT_SYMBOL(vfs_readf);
 
 vfs_writef_t vfs_writef(struct file *file)
 {
@@ -515,6 +516,7 @@ vfs_writef_t vfs_writef(struct file *file)
 		return new_sync_write;
 	return ERR_PTR(-ENOSYS);
 }
+EXPORT_SYMBOL(vfs_writef);
 
 ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos)
 {
diff --git a/fs/splice.c b/fs/splice.c
index 5f8385a..f76067e 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1115,6 +1115,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
 
 	return splice_write(pipe, out, ppos, len, flags);
 }
+EXPORT_SYMBOL(do_splice_from);
 
 /*
  * Attempt to initiate a splice from a file to a pipe.
@@ -1141,6 +1142,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
 
 	return splice_read(in, ppos, pipe, len, flags);
 }
+EXPORT_SYMBOL(do_splice_to);
 
 /**
  * splice_direct_to_actor - splices data directly between two non-pipes
diff --git a/fs/xattr.c b/fs/xattr.c
index 072fee1..a7677af 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -207,6 +207,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
 	*xattr_value = value;
 	return error;
 }
+EXPORT_SYMBOL(vfs_getxattr_alloc);
 
 /* Compare an extended attribute value with the given value */
 int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
diff --git a/security/commoncap.c b/security/commoncap.c
index d103f5a4..393654e 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -970,12 +970,14 @@ int cap_mmap_addr(unsigned long addr)
 	}
 	return ret;
 }
+EXPORT_SYMBOL(cap_mmap_addr);
 
 int cap_mmap_file(struct file *file, unsigned long reqprot,
 		  unsigned long prot, unsigned long flags)
 {
 	return 0;
 }
+EXPORT_SYMBOL(cap_mmap_file);
 
 #ifdef CONFIG_SECURITY
 
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 188c1d2..426d9af 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -7,6 +7,7 @@
 #include <linux/device_cgroup.h>
 #include <linux/cgroup.h>
 #include <linux/ctype.h>
+#include <linux/export.h>
 #include <linux/list.h>
 #include <linux/uaccess.h>
 #include <linux/seq_file.h>
@@ -849,6 +850,7 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)
 	return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
 			access);
 }
+EXPORT_SYMBOL(__devcgroup_inode_permission);
 
 int devcgroup_inode_mknod(int mode, dev_t dev)
 {
diff --git a/security/security.c b/security/security.c
index 595fffa..346bad6 100644
--- a/security/security.c
+++ b/security/security.c
@@ -438,6 +438,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
 		return 0;
 	return call_int_hook(path_rmdir, 0, dir, dentry);
 }
+EXPORT_SYMBOL(security_path_rmdir);
 
 int security_path_unlink(struct path *dir, struct dentry *dentry)
 {
@@ -454,6 +455,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
 		return 0;
 	return call_int_hook(path_symlink, 0, dir, dentry, old_name);
 }
+EXPORT_SYMBOL(security_path_symlink);
 
 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
 		       struct dentry *new_dentry)
@@ -462,6 +464,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
 		return 0;
 	return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
 }
+EXPORT_SYMBOL(security_path_link);
 
 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
 			 struct path *new_dir, struct dentry *new_dentry,
@@ -489,6 +492,7 @@ int security_path_truncate(struct path *path)
 		return 0;
 	return call_int_hook(path_truncate, 0, path);
 }
+EXPORT_SYMBOL(security_path_truncate);
 
 int security_path_chmod(struct path *path, umode_t mode)
 {
@@ -496,6 +500,7 @@ int security_path_chmod(struct path *path, umode_t mode)
 		return 0;
 	return call_int_hook(path_chmod, 0, path, mode);
 }
+EXPORT_SYMBOL(security_path_chmod);
 
 int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
 {
@@ -503,6 +508,7 @@ int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
 		return 0;
 	return call_int_hook(path_chown, 0, path, uid, gid);
 }
+EXPORT_SYMBOL(security_path_chown);
 
 int security_path_chroot(struct path *path)
 {
@@ -588,6 +594,7 @@ int security_inode_readlink(struct dentry *dentry)
 		return 0;
 	return call_int_hook(inode_readlink, 0, dentry);
 }
+EXPORT_SYMBOL(security_inode_readlink);
 
 int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
 			       bool rcu)
@@ -603,6 +610,7 @@ int security_inode_permission(struct inode *inode, int mask)
 		return 0;
 	return call_int_hook(inode_permission, 0, inode, mask);
 }
+EXPORT_SYMBOL(security_inode_permission);
 
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 {
@@ -741,6 +749,7 @@ int security_file_permission(struct file *file, int mask)
 
 	return fsnotify_perm(file, mask);
 }
+EXPORT_SYMBOL(security_file_permission);
 
 int security_file_alloc(struct file *file)
 {
@@ -800,6 +809,7 @@ int security_mmap_file(struct file *file, unsigned long prot,
 		return ret;
 	return ima_file_mmap(file, prot);
 }
+EXPORT_SYMBOL(security_mmap_file);
 
 int security_mmap_addr(unsigned long addr)
 {
-- 
2.4.6

>From 8722d5d505023be0bad9e5328641a1b112c5acbb Mon Sep 17 00:00:00 2001
From: Andy Whitcroft <a...@canonical.com>
Date: Thu, 30 Jul 2015 12:59:58 +0100
Subject: [PATCH] UBUNTU: aufs4: aufs4-loopback.patch

Signed-off-by: Andy Whitcroft <a...@canonical.com>
---
 drivers/block/loop.c | 47 ++++++++++++++++++++++++++++++++++++++++++-----
 drivers/block/loop.h |  2 +-
 fs/aufs/f_op.c       |  2 +-
 fs/aufs/loop.c       | 16 ++++++++++++++++
 fs/aufs/loop.h       |  6 ++++++
 fs/aufs/super.c      |  5 ++++-
 include/linux/fs.h   |  4 ++++
 7 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 23103ad..5c3263f 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -417,7 +417,7 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
 }
 
 struct switch_request {
-	struct file *file;
+	struct file *file, *virt_file;
 	struct completion wait;
 };
 
@@ -437,6 +437,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);
@@ -448,11 +449,13 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
  * 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;
 
 	w.file = file;
+	w.virt_file = virt_file;
 
 	/* freeze queue and wait for completion of scheduled requests */
 	blk_mq_freeze_queue(lo->lo_queue);
@@ -471,7 +474,16 @@ static int loop_switch(struct loop_device *lo, struct file *file)
  */
 static int loop_flush(struct loop_device *lo)
 {
-	return loop_switch(lo, NULL);
+	return loop_switch(lo, NULL, NULL);
+}
+
+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,
@@ -508,6 +520,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;
 
@@ -524,9 +537,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;
 
@@ -538,17 +558,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)
 		loop_reread_partitions(lo, bdev);
 	return 0;
 
  out_putf:
 	fput(file);
+	if (virt_file)
+		fput(virt_file);
  out:
 	return error;
 }
@@ -709,7 +733,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;
@@ -724,6 +748,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)
@@ -778,6 +808,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;
@@ -809,6 +840,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 
  out_putf:
 	fput(file);
+	if (virt_file)
+		fput(virt_file);
  out:
 	/* This is safe: open() is still holding a reference. */
 	module_put(THIS_MODULE);
@@ -855,6 +888,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;
 
@@ -886,6 +920,7 @@ static int loop_clr_fd(struct loop_device *lo)
 	spin_lock_irq(&lo->lo_lock);
 	lo->lo_state = Lo_rundown;
 	lo->lo_backing_file = NULL;
+	lo->lo_backing_virt_file = NULL;
 	spin_unlock_irq(&lo->lo_lock);
 
 	loop_release_xfer(lo);
@@ -931,6 +966,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 25e8997..93b6fce 100644
--- 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;
+	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 34037c7..2c34864 100644
--- a/fs/aufs/f_op.c
+++ b/fs/aufs/f_op.c
@@ -402,7 +402,7 @@ static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
 	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
index 6775684..eb20453 100644
--- a/fs/aufs/loop.c
+++ b/fs/aufs/loop.c
@@ -143,3 +143,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_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
index 0c28c23..de1e159 100644
--- a/fs/aufs/loop.h
+++ b/fs/aufs/loop.h
@@ -38,7 +38,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)
@@ -46,6 +50,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 6b7f38e..931a257 100644
--- a/fs/aufs/super.c
+++ b/fs/aufs/super.c
@@ -820,7 +820,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 394b619..9fb85eb 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1723,6 +1723,10 @@ struct super_operations {
 				  struct shrink_control *);
 	long (*free_cached_objects)(struct super_block *,
 				    struct shrink_control *);
+#if defined(CONFIG_BLK_DEV_LOOP) ||  defined(CONFIG_BLK_DEV_LOOP_MODULE)
+	/* and aufs */
+	struct file *(*real_loop)(struct file *);
+#endif
 };
 
 /*
-- 
2.4.6

>From 4a59b42745a0cb8faf91e71977f65574e6820414 Mon Sep 17 00:00:00 2001
From: Andy Whitcroft <a...@canonical.com>
Date: Wed, 29 Jul 2015 14:49:45 +0100
Subject: [PATCH] aufs: follow change to follow_link() calling convention

Signed-off-by: Andy Whitcroft <a...@canonical.com>
---
 fs/aufs/i_op.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
index 17364e4..312f24d 100644
--- a/fs/aufs/i_op.c
+++ b/fs/aufs/i_op.c
@@ -1288,7 +1288,7 @@ out:
 	return err;
 }
 
-static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static const char *aufs_follow_link(struct dentry *dentry, void **cookie)
 {
 	int err;
 	mm_segment_t old_fs;
@@ -1317,9 +1317,9 @@ static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
 
 	if (err >= 0) {
 		buf.k[err] = 0;
+
 		/* will be freed by put_link */
-		nd_set_link(nd, buf.k);
-		return NULL; /* success */
+		return *cookie = buf.k;
 	}
 
 out_name:
@@ -1329,14 +1329,10 @@ out:
 	return ERR_PTR(err);
 }
 
-static void aufs_put_link(struct dentry *dentry __maybe_unused,
-			  struct nameidata *nd, void *cookie __maybe_unused)
+static void aufs_put_link(struct inode *inode __maybe_unused, void *cookie)
 {
-	char *p;
-
-	p = nd_get_link(nd);
-	if (!IS_ERR_OR_NULL(p))
-		free_page((unsigned long)p);
+	if (!IS_ERR_OR_NULL(cookie))
+		free_page((unsigned long)cookie);
 }
 
 /* ---------------------------------------------------------------------- */
-- 
2.4.6

------------------------------------------------------------------------------

Reply via email to