--- /dev/null
+From: Tony Jones <tonyj@suse.de>
+Subject: Add struct vfsmount parameters to vfs_link()
+
+The vfsmount will be passed down to the LSM hook so that LSMs can compute
+pathnames.
+
+Signed-off-by: Tony Jones <tonyj@suse.de>
+Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
+Signed-off-by: John Johansen <jjohansen@suse.de>
+
+---
+ fs/ecryptfs/inode.c | 9 +++++++--
+ fs/namei.c | 6 ++++--
+ fs/nfsd/vfs.c | 3 ++-
+ include/linux/fs.h | 2 +-
+ 4 files changed, 14 insertions(+), 6 deletions(-)
+
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -403,19 +403,24 @@ static int ecryptfs_link(struct dentry *
+ struct dentry *new_dentry)
+ {
+ struct dentry *lower_old_dentry;
++ struct vfsmount *lower_old_mnt;
+ struct dentry *lower_new_dentry;
++ struct vfsmount *lower_new_mnt;
+ struct dentry *lower_dir_dentry;
+ u64 file_size_save;
+ int rc;
+
+ file_size_save = i_size_read(old_dentry->d_inode);
+ lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
++ lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
+ lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
++ lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
+ dget(lower_old_dentry);
+ dget(lower_new_dentry);
+ lower_dir_dentry = lock_parent(lower_new_dentry);
+- rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
+- lower_new_dentry);
++ rc = vfs_link(lower_old_dentry, lower_old_mnt,
++ lower_dir_dentry->d_inode, lower_new_dentry,
++ lower_new_mnt);
+ if (rc || !lower_new_dentry->d_inode)
+ goto out_lock;
+ rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -2412,7 +2412,7 @@ SYSCALL_DEFINE2(symlink, const char __us
+ return sys_symlinkat(oldname, AT_FDCWD, newname);
+ }
+
+-int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
++int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt)
+ {
+ struct inode *inode = old_dentry->d_inode;
+ int error;
+@@ -2490,7 +2490,9 @@ SYSCALL_DEFINE5(linkat, int, olddfd, con
+ error = mnt_want_write(nd.path.mnt);
+ if (error)
+ goto out_dput;
+- error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
++ error = vfs_link(old_path.dentry, old_path.mnt,
++ nd.path.dentry->d_inode,
++ new_dentry, nd.path.mnt);
+ mnt_drop_write(nd.path.mnt);
+ out_dput:
+ dput(new_dentry);
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1650,7 +1650,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
+ err = nfserrno(host_err);
+ goto out_dput;
+ }
+- host_err = vfs_link(dold, dirp, dnew);
++ host_err = vfs_link(dold, tfhp->fh_export->ex_path.mnt, dirp,
++ dnew, ffhp->fh_export->ex_path.mnt);
+ if (!host_err) {
+ if (EX_ISSYNC(ffhp->fh_export)) {
+ err = nfserrno(nfsd_sync_dir(ddir));
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1181,7 +1181,7 @@ extern int vfs_create(struct inode *, st
+ extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
+ extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
+ extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *);
+-extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
++extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
+ extern int vfs_rmdir(struct inode *, struct dentry *);
+ extern int vfs_unlink(struct inode *, struct dentry *);
+ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);