--- /dev/null
+diff --git a/fs/wrapfs/inode.c b/fs/wrapfs/inode.c
+index ab0aff1abbd9..7adc0e7c6a2d 100644
+--- a/fs/wrapfs/inode.c
++++ b/fs/wrapfs/inode.c
+@@ -8,8 +8,8 @@
+
+ #include "wrapfs.h"
+
+-static int wrapfs_create(struct inode *dir, struct dentry *dentry,
+- umode_t mode, bool want_excl)
++static int wrapfs_create(struct user_namespace *mnt_userns, struct inode *dir,
++ struct dentry *dentry, umode_t mode, bool want_excl)
+ {
+ int err;
+ struct dentry *lower_dentry;
+@@ -20,7 +20,8 @@ static int wrapfs_create(struct inode *dir, struct dentry *dentry,
+ lower_dentry = lower_path.dentry;
+ lower_parent_dentry = lock_parent(lower_dentry);
+
+- err = vfs_create(d_inode(lower_parent_dentry), lower_dentry, mode,
++ err = vfs_create(mnt_user_ns(lower_path.mnt),
++ d_inode(lower_parent_dentry), lower_dentry, mode,
+ want_excl);
+ if (err)
+ goto out;
+@@ -53,8 +54,12 @@ static int wrapfs_link(struct dentry *old_dentry, struct inode *dir,
+ lower_new_dentry = lower_new_path.dentry;
+ lower_dir_dentry = lock_parent(lower_new_dentry);
+
+- err = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry),
+- lower_new_dentry, NULL);
++ /*
++ * It doesn't matter whether we take lower_new_path.mnt or
++ * lower_old_path.mnt because these will always be the same vfsmount.
++ */
++ err = vfs_link(lower_old_dentry, mnt_user_ns(lower_new_path.mnt),
++ d_inode(lower_dir_dentry), lower_new_dentry, NULL);
+ if (err || d_really_is_negative(lower_new_dentry))
+ goto out;
+
+@@ -91,7 +96,8 @@ static int wrapfs_unlink(struct inode *dir, struct dentry *dentry)
+ goto out;
+ }
+
+- err = vfs_unlink(lower_dir_inode, lower_dentry, NULL);
++ err = vfs_unlink(mnt_user_ns(lower_path.mnt), lower_dir_inode,
++ lower_dentry, NULL);
+
+ /*
+ * Note: unlinking on top of NFS can cause silly-renamed files.
+@@ -117,8 +123,8 @@ static int wrapfs_unlink(struct inode *dir, struct dentry *dentry)
+ return err;
+ }
+
+-static int wrapfs_symlink(struct inode *dir, struct dentry *dentry,
+- const char *symname)
++static int wrapfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
++ struct dentry *dentry, const char *symname)
+ {
+ int err;
+ struct dentry *lower_dentry;
+@@ -129,7 +135,8 @@ static int wrapfs_symlink(struct inode *dir, struct dentry *dentry,
+ lower_dentry = lower_path.dentry;
+ lower_parent_dentry = lock_parent(lower_dentry);
+
+- err = vfs_symlink(d_inode(lower_parent_dentry), lower_dentry, symname);
++ err = vfs_symlink(mnt_user_ns(lower_path.mnt),
++ d_inode(lower_parent_dentry), lower_dentry, symname);
+ if (err)
+ goto out;
+ err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
+@@ -144,7 +151,8 @@ static int wrapfs_symlink(struct inode *dir, struct dentry *dentry,
+ return err;
+ }
+
+-static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
++static int wrapfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
++ struct dentry *dentry, umode_t mode)
+ {
+ int err;
+ struct dentry *lower_dentry;
+@@ -155,7 +163,8 @@ static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ lower_dentry = lower_path.dentry;
+ lower_parent_dentry = lock_parent(lower_dentry);
+
+- err = vfs_mkdir(d_inode(lower_parent_dentry), lower_dentry, mode);
++ err = vfs_mkdir(mnt_user_ns(lower_path.mnt),
++ d_inode(lower_parent_dentry), lower_dentry, mode);
+ if (err)
+ goto out;
+
+@@ -190,7 +199,8 @@ static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry)
+ goto out;
+ }
+
+- err = vfs_rmdir(d_inode(lower_dir_dentry), lower_dentry);
++ err = vfs_rmdir(mnt_user_ns(lower_path.mnt), d_inode(lower_dir_dentry),
++ lower_dentry);
+ if (err)
+ goto out;
+
+@@ -207,8 +217,8 @@ static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry)
+ return err;
+ }
+
+-static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+- dev_t dev)
++static int wrapfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
++ struct dentry *dentry, umode_t mode, dev_t dev)
+ {
+ int err;
+ struct dentry *lower_dentry;
+@@ -219,7 +229,8 @@ static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+ lower_dentry = lower_path.dentry;
+ lower_parent_dentry = lock_parent(lower_dentry);
+
+- err = vfs_mknod(d_inode(lower_parent_dentry), lower_dentry, mode, dev);
++ err = vfs_mknod(mnt_user_ns(lower_path.mnt),
++ d_inode(lower_parent_dentry), lower_dentry, mode, dev);
+ if (err)
+ goto out;
+
+@@ -239,7 +250,8 @@ static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+ * The locking rules in wrapfs_rename are complex. We could use a simpler
+ * superblock-level name-space lock for renames and copy-ups.
+ */
+-static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++static int wrapfs_rename(struct user_namespace *mnt_userns,
++ struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
+ {
+@@ -250,6 +262,7 @@ static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct dentry *lower_new_dir_dentry = NULL;
+ struct dentry *trap = NULL;
+ struct path lower_old_path, lower_new_path;
++ struct renamedata rd = {};
+
+ if (flags)
+ return -EINVAL;
+@@ -280,9 +293,13 @@ static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ goto out;
+ }
+
+- err = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry,
+- d_inode(lower_new_dir_dentry), lower_new_dentry,
+- NULL, 0);
++ rd.old_mnt_userns = mnt_user_ns(lower_old_path.mnt);
++ rd.old_dir = d_inode(lower_old_dir_dentry);
++ rd.old_dentry = lower_old_dentry;
++ rd.new_mnt_userns = mnt_user_ns(lower_new_path.mnt);
++ rd.new_dir = d_inode(lower_new_dir_dentry);
++ rd.new_dentry = lower_new_dentry;
++ err = vfs_rename(&rd);
+ if (err)
+ goto out;
+
+@@ -348,17 +365,30 @@ static const char *wrapfs_get_link(struct dentry *dentry, struct inode *inode,
+ return buf;
+ }
+
+-static int wrapfs_permission(struct inode *inode, int mask)
++static int wrapfs_permission(struct user_namespace *mnt_userns,
++ struct inode *inode, int mask)
+ {
+ struct inode *lower_inode;
++ struct dentry *dentry = NULL;
++ struct path lower_path;
+ int err;
+
++ /*
++ * Grab the first dentry for this inode. All dentries should belong
++ * to the same vfsmount so it doesn't matter which one we use.
++ */
++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias)
++ break;
++ BUG_ON(!dentry);
++ wrapfs_get_lower_path(dentry, &lower_path);
+ lower_inode = wrapfs_lower_inode(inode);
+- err = inode_permission(lower_inode, mask);
++ err = inode_permission(mnt_user_ns(lower_path.mnt), lower_inode, mask);
++ wrapfs_put_lower_path(dentry, &lower_path);
+ return err;
+ }
+
+-static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
++static int wrapfs_setattr(struct user_namespace *mnt_userns,
++ struct dentry *dentry, struct iattr *ia)
+ {
+ int err;
+ struct dentry *lower_dentry;
+@@ -368,17 +398,17 @@ static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
+ struct iattr lower_ia;
+
+ inode = d_inode(dentry);
++ wrapfs_get_lower_path(dentry, &lower_path);
+
+ /*
+ * Check if user has permission to change inode. We don't check if
+ * this user can change the lower inode: that should happen when
+ * calling notify_change on the lower inode.
+ */
+- err = setattr_prepare(dentry, ia);
++ err = setattr_prepare(mnt_user_ns(lower_path.mnt), dentry, ia);
+ if (err)
+- goto out_err;
++ goto out;
+
+- wrapfs_get_lower_path(dentry, &lower_path);
+ lower_dentry = lower_path.dentry;
+ lower_inode = wrapfs_lower_inode(inode);
+
+@@ -416,7 +446,8 @@ static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
+ * tries to open(), unlink(), then ftruncate() a file.
+ */
+ inode_lock(d_inode(lower_dentry));
+- err = notify_change(lower_dentry, &lower_ia, /* note: lower_ia */
++ err = notify_change(mnt_user_ns(lower_path.mnt), lower_dentry,
++ &lower_ia, /* note: lower_ia */
+ NULL);
+ inode_unlock(d_inode(lower_dentry));
+ if (err)
+@@ -432,11 +463,11 @@ static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
+
+ out:
+ wrapfs_put_lower_path(dentry, &lower_path);
+-out_err:
+ return err;
+ }
+
+-static int wrapfs_getattr(const struct path *path, struct kstat *stat,
++static int wrapfs_getattr(struct user_namespace *mnt_userns,
++ const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int flags)
+ {
+ int err;
+@@ -450,7 +481,7 @@ static int wrapfs_getattr(const struct path *path, struct kstat *stat,
+ goto out;
+ fsstack_copy_attr_all(d_inode(dentry),
+ d_inode(lower_path.dentry));
+- generic_fillattr(d_inode(dentry), stat);
++ generic_fillattr(mnt_user_ns(lower_path.mnt), d_inode(dentry), stat);
+ stat->blocks = lower_stat.blocks;
+ out:
+ wrapfs_put_lower_path(dentry, &lower_path);
+@@ -470,7 +501,8 @@ wrapfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+- err = vfs_setxattr(lower_dentry, name, value, size, flags);
++ err = vfs_setxattr(mnt_user_ns(lower_path.mnt), lower_dentry, name,
++ value, size, flags);
+ if (err)
+ goto out;
+ fsstack_copy_attr_all(d_inode(dentry),
+@@ -496,7 +528,8 @@ wrapfs_getxattr(struct dentry *dentry, struct inode *inode,
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+- err = vfs_getxattr(lower_dentry, name, buffer, size);
++ err = vfs_getxattr(mnt_user_ns(lower_path.mnt), lower_dentry, name,
++ buffer, size);
+ if (err)
+ goto out;
+ fsstack_copy_attr_atime(d_inode(dentry),
+@@ -544,7 +577,7 @@ wrapfs_removexattr(struct dentry *dentry, struct inode *inode, const char *name)
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+- err = vfs_removexattr(lower_dentry, name);
++ err = vfs_removexattr(mnt_user_ns(lower_path.mnt), lower_dentry, name);
+ if (err)
+ goto out;
+ fsstack_copy_attr_all(d_inode(dentry), lower_inode);
+@@ -592,6 +625,7 @@ static int wrapfs_xattr_get(const struct xattr_handler *handler,
+ }
+
+ static int wrapfs_xattr_set(const struct xattr_handler *handler,
++ struct user_namespace *mnt_userns,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value, size_t size,
+ int flags)
+diff --git a/fs/wrapfs/mmap.c b/fs/wrapfs/mmap.c
+index 9897fa585b97..7083a9b871ac 100644
+--- a/fs/wrapfs/mmap.c
++++ b/fs/wrapfs/mmap.c
+@@ -15,6 +15,7 @@ static vm_fault_t wrapfs_fault(struct vm_fault *vmf)
+ struct file *file, *lower_file;
+ const struct vm_operations_struct *lower_vm_ops;
+ struct vm_area_struct lower_vma;
++ struct vm_area_struct **vma_p = (struct vm_area_struct**)&vmf->vma;
+
+ memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
+ file = lower_vma.vm_file;
+@@ -33,9 +34,9 @@ static vm_fault_t wrapfs_fault(struct vm_fault *vmf)
+ * take an explicit file pointer.
+ */
+ lower_vma.vm_file = lower_file;
+- vmf->vma = &lower_vma; /* override vma temporarily */
++ *vma_p = &lower_vma;
+ err = lower_vm_ops->fault(vmf);
+- vmf->vma = vma; /* restore vma*/
++ *vma_p = vma;
+ return err;
+ }
+
+@@ -46,6 +47,7 @@ static vm_fault_t wrapfs_page_mkwrite(struct vm_fault *vmf)
+ struct file *file, *lower_file;
+ const struct vm_operations_struct *lower_vm_ops;
+ struct vm_area_struct lower_vma;
++ struct vm_area_struct **vma_p = (struct vm_area_struct**)&vmf->vma;
+
+ memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
+ file = lower_vma.vm_file;
+@@ -67,9 +69,9 @@ static vm_fault_t wrapfs_page_mkwrite(struct vm_fault *vmf)
+ * ->page_mkwrite to take an explicit file pointer.
+ */
+ lower_vma.vm_file = lower_file;
+- vmf->vma = &lower_vma; /* override vma temporarily */
++ *vma_p = &lower_vma;
+ err = lower_vm_ops->page_mkwrite(vmf);
+- vmf->vma = vma; /* restore vma */
++ *vma_p = vma;
+ out:
+ return err;
+ }