if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       err = vfs_mkdir(&init_user_ns, d_inode(path.dentry), dentry, mode);
+       err = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode);
        if (!err)
                /* mark as kernel-created inode */
                d_inode(dentry)->i_private = &thread;
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       err = vfs_mknod(&init_user_ns, d_inode(path.dentry), dentry, mode,
+       err = vfs_mknod(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode,
                        dev->devt);
        if (!err) {
                struct iattr newattrs;
                newattrs.ia_gid = gid;
                newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
                inode_lock(d_inode(dentry));
-               notify_change(&init_user_ns, dentry, &newattrs, NULL);
+               notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL);
                inode_unlock(d_inode(dentry));
 
                /* mark as kernel-created inode */
                return PTR_ERR(dentry);
        if (d_really_is_positive(dentry)) {
                if (d_inode(dentry)->i_private == &thread)
-                       err = vfs_rmdir(&init_user_ns, d_inode(parent.dentry),
+                       err = vfs_rmdir(&nop_mnt_idmap, d_inode(parent.dentry),
                                        dentry);
                else
                        err = -EPERM;
                        newattrs.ia_valid =
                                ATTR_UID|ATTR_GID|ATTR_MODE;
                        inode_lock(d_inode(dentry));
-                       notify_change(&init_user_ns, dentry, &newattrs, NULL);
+                       notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL);
                        inode_unlock(d_inode(dentry));
-                       err = vfs_unlink(&init_user_ns, d_inode(parent.dentry),
+                       err = vfs_unlink(&nop_mnt_idmap, d_inode(parent.dentry),
                                         dentry, NULL);
                        if (!err || err == -ENOENT)
                                deleted = 1;
 
 
 /**
  * notify_change - modify attributes of a filesytem object
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dentry:    object affected
  * @attr:      new attributes
  * @delegated_inode: returns inode, if the inode is delegated
  * the file open for write, as there can be no conflicting delegation in
  * that case.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then
- * take care to map the inode according to @mnt_userns before checking
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then
+ * take care to map the inode according to @idmap before checking
  * permissions. On non-idmapped mounts or if permission checking is to be
- * performed on the raw inode simply passs init_user_ns.
+ * performed on the raw inode simply pass @nop_mnt_idmap.
  */
-int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
+int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
                  struct iattr *attr, struct inode **delegated_inode)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        struct inode *inode = dentry->d_inode;
        umode_t mode = inode->i_mode;
        int error;
 
                newattrs.ia_size = oi_size & PAGE_MASK;
                ret = cachefiles_inject_remove_error();
                if (ret == 0)
-                       ret = notify_change(&init_user_ns, file->f_path.dentry,
+                       ret = notify_change(&nop_mnt_idmap, file->f_path.dentry,
                                            &newattrs, NULL);
                if (ret < 0)
                        goto truncate_failed;
        newattrs.ia_size = ni_size;
        ret = cachefiles_inject_write_error();
        if (ret == 0)
-               ret = notify_change(&init_user_ns, file->f_path.dentry,
+               ret = notify_change(&nop_mnt_idmap, file->f_path.dentry,
                                    &newattrs, NULL);
 
 truncate_failed:
 
                        goto mkdir_error;
                ret = cachefiles_inject_write_error();
                if (ret == 0)
-                       ret = vfs_mkdir(&init_user_ns, d_inode(dir), subdir, 0700);
+                       ret = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700);
                if (ret < 0) {
                        trace_cachefiles_vfs_error(NULL, d_inode(dir), ret,
                                                   cachefiles_trace_mkdir_error);
 
        ret = cachefiles_inject_remove_error();
        if (ret == 0) {
-               ret = vfs_unlink(&init_user_ns, d_backing_inode(dir), dentry, NULL);
+               ret = vfs_unlink(&nop_mnt_idmap, d_backing_inode(dir), dentry, NULL);
                if (ret == -EIO)
                        cachefiles_io_error(cache, "Unlink failed");
        }
                cachefiles_io_error(cache, "Rename security error %d", ret);
        } else {
                struct renamedata rd = {
-                       .old_mnt_userns = &init_user_ns,
+                       .old_mnt_idmap  = &nop_mnt_idmap,
                        .old_dir        = d_inode(dir),
                        .old_dentry     = rep,
-                       .new_mnt_userns = &init_user_ns,
+                       .new_mnt_idmap  = &nop_mnt_idmap,
                        .new_dir        = d_inode(cache->graveyard),
                        .new_dentry     = grave,
                };
 
        ret = cachefiles_inject_write_error();
        if (ret == 0) {
-               file = vfs_tmpfile_open(&init_user_ns, &parentpath, S_IFREG,
+               file = vfs_tmpfile_open(&nop_mnt_idmap, &parentpath, S_IFREG,
                                        O_RDWR | O_LARGEFILE | O_DIRECT,
                                        cache->cache_cred);
                ret = PTR_ERR_OR_ZERO(file);
 
        ret = cachefiles_inject_read_error();
        if (ret == 0)
-               ret = vfs_link(object->file->f_path.dentry, &init_user_ns,
+               ret = vfs_link(object->file->f_path.dentry, &nop_mnt_idmap,
                               d_inode(fan), dentry, NULL);
        if (ret < 0) {
                trace_cachefiles_vfs_error(object, d_inode(fan), ret,
 
                        goto close_fail;
                }
        } else {
+               struct mnt_idmap *idmap;
                struct user_namespace *mnt_userns;
                struct inode *inode;
                int open_flags = O_CREAT | O_RDWR | O_NOFOLLOW |
                 * a process dumps core while its cwd is e.g. on a vfat
                 * filesystem.
                 */
-               mnt_userns = file_mnt_user_ns(cprm.file);
+               idmap = file_mnt_idmap(cprm.file);
+               mnt_userns = mnt_idmap_owner(idmap);
                if (!vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode),
                                    current_fsuid())) {
                        pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n",
                }
                if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
                        goto close_fail;
-               if (do_truncate(mnt_userns, cprm.file->f_path.dentry,
+               if (do_truncate(idmap, cprm.file->f_path.dentry,
                                0, 0, cprm.file))
                        goto close_fail;
        }
 
                if (d_unhashed(lower_dentry))
                        rc = -EINVAL;
                else
-                       rc = vfs_unlink(&init_user_ns, lower_dir, lower_dentry,
+                       rc = vfs_unlink(&nop_mnt_idmap, lower_dir, lower_dentry,
                                        NULL);
        }
        if (rc) {
 
        rc = lock_parent(ecryptfs_dentry, &lower_dentry, &lower_dir);
        if (!rc)
-               rc = vfs_create(&init_user_ns, lower_dir,
+               rc = vfs_create(&nop_mnt_idmap, lower_dir,
                                lower_dentry, mode, true);
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
        inode = __ecryptfs_get_inode(d_inode(lower_dentry),
                                     directory_inode->i_sb);
        if (IS_ERR(inode)) {
-               vfs_unlink(&init_user_ns, lower_dir, lower_dentry, NULL);
+               vfs_unlink(&nop_mnt_idmap, lower_dir, lower_dentry, NULL);
                goto out_lock;
        }
        fsstack_copy_attr_times(directory_inode, lower_dir);
        lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
        rc = lock_parent(new_dentry, &lower_new_dentry, &lower_dir);
        if (!rc)
-               rc = vfs_link(lower_old_dentry, &init_user_ns, lower_dir,
+               rc = vfs_link(lower_old_dentry, &nop_mnt_idmap, lower_dir,
                              lower_new_dentry, NULL);
        if (rc || d_really_is_negative(lower_new_dentry))
                goto out_lock;
                                                  strlen(symname));
        if (rc)
                goto out_lock;
-       rc = vfs_symlink(&init_user_ns, lower_dir, lower_dentry,
+       rc = vfs_symlink(&nop_mnt_idmap, lower_dir, lower_dentry,
                         encoded_symname);
        kfree(encoded_symname);
        if (rc || d_really_is_negative(lower_dentry))
 
        rc = lock_parent(dentry, &lower_dentry, &lower_dir);
        if (!rc)
-               rc = vfs_mkdir(&init_user_ns, lower_dir,
+               rc = vfs_mkdir(&nop_mnt_idmap, lower_dir,
                               lower_dentry, mode);
        if (rc || d_really_is_negative(lower_dentry))
                goto out;
                if (d_unhashed(lower_dentry))
                        rc = -EINVAL;
                else
-                       rc = vfs_rmdir(&init_user_ns, lower_dir, lower_dentry);
+                       rc = vfs_rmdir(&nop_mnt_idmap, lower_dir, lower_dentry);
        }
        if (!rc) {
                clear_nlink(d_inode(dentry));
 
        rc = lock_parent(dentry, &lower_dentry, &lower_dir);
        if (!rc)
-               rc = vfs_mknod(&init_user_ns, lower_dir,
+               rc = vfs_mknod(&nop_mnt_idmap, lower_dir,
                               lower_dentry, mode, dev);
        if (rc || d_really_is_negative(lower_dentry))
                goto out;
                goto out_lock;
        }
 
-       rd.old_mnt_userns       = &init_user_ns;
+       rd.old_mnt_idmap        = &nop_mnt_idmap;
        rd.old_dir              = d_inode(lower_old_dir_dentry);
        rd.old_dentry           = lower_old_dentry;
-       rd.new_mnt_userns       = &init_user_ns;
+       rd.new_mnt_idmap        = &nop_mnt_idmap;
        rd.new_dir              = d_inode(lower_new_dir_dentry);
        rd.new_dentry           = lower_new_dentry;
        rc = vfs_rename(&rd);
                struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
 
                inode_lock(d_inode(lower_dentry));
-               rc = notify_change(&init_user_ns, lower_dentry,
+               rc = notify_change(&nop_mnt_idmap, lower_dentry,
                                   &lower_ia, NULL);
                inode_unlock(d_inode(lower_dentry));
        }
                lower_ia.ia_valid &= ~ATTR_MODE;
 
        inode_lock(d_inode(lower_dentry));
-       rc = notify_change(&init_user_ns, lower_dentry, &lower_ia, NULL);
+       rc = notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, NULL);
        inode_unlock(d_inode(lower_dentry));
 out:
        fsstack_copy_attr_all(inode, lower_inode);
 
                mode &= ~current_umask();
        error = security_path_mknod(&path, dentry, mode, dev);
        if (!error)
-               error = vfs_mknod(mnt_user_ns(path.mnt), path.dentry->d_inode,
+               error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode,
                                  dentry, mode, new_decode_dev(dev));
        done_path_create(&path, dentry);
        return error;
 {
        struct dentry *new_dentry;
        struct path old_path, new_path;
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        int error;
 
        error = -EXDEV;
        if (old_path.mnt != new_path.mnt)
                goto out_dput;
-       mnt_userns = mnt_user_ns(new_path.mnt);
+       idmap = mnt_idmap(new_path.mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        error = may_linkat(mnt_userns, &old_path);
        if (unlikely(error))
                goto out_dput;
        error = security_path_link(old_path.dentry, &new_path, new_dentry);
        if (error)
                goto out_dput;
-       error = vfs_link(old_path.dentry, mnt_userns, new_path.dentry->d_inode,
+       error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
                         new_dentry, NULL);
 out_dput:
        done_path_create(&new_path, new_dentry);
                return PTR_ERR(dentry);
        error = security_path_symlink(&path, dentry, oldname);
        if (!error)
-               error = vfs_symlink(mnt_user_ns(path.mnt), path.dentry->d_inode,
+               error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
                                    dentry, oldname);
        done_path_create(&path, dentry);
        return error;
                mode &= ~current_umask();
        error = security_path_mkdir(&path, dentry, mode);
        if (!error)
-               error = vfs_mkdir(mnt_user_ns(path.mnt), path.dentry->d_inode,
+               error = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
                                  dentry, mode);
        done_path_create(&path, dentry);
        return error;
 
        return mask;
 }
 
-static int __remove_privs(struct user_namespace *mnt_userns,
+static int __remove_privs(struct mnt_idmap *idmap,
                          struct dentry *dentry, int kill)
 {
        struct iattr newattrs;
         * Note we call this on write, so notify_change will not
         * encounter any conflicting delegations:
         */
-       return notify_change(mnt_userns, dentry, &newattrs, NULL);
+       return notify_change(idmap, dentry, &newattrs, NULL);
 }
 
 static int __file_remove_privs(struct file *file, unsigned int flags)
                if (flags & IOCB_NOWAIT)
                        return -EAGAIN;
 
-               error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
+               error = __remove_privs(file_mnt_idmap(file), dentry, kill);
        }
 
        if (!error)
 
        struct iattr attrs;
        struct file *filp;
        struct inode *inode;
+       struct mnt_idmap *idmap;
        struct user_namespace *user_ns;
        int rc = 0;
 
        attrs.ia_valid = 0;
        filp = fp->filp;
        inode = file_inode(filp);
-       user_ns = file_mnt_user_ns(filp);
+       idmap = file_mnt_idmap(filp);
+       user_ns = mnt_idmap_owner(idmap);
 
        if (file_info->CreationTime)
                fp->create_time = le64_to_cpu(file_info->CreationTime);
                inode_lock(inode);
                inode->i_ctime = attrs.ia_ctime;
                attrs.ia_valid &= ~ATTR_CTIME;
-               rc = notify_change(user_ns, dentry, &attrs, NULL);
+               rc = notify_change(idmap, dentry, &attrs, NULL);
                inode_unlock(inode);
        }
        return rc;
 
        int rc;
        struct smb_fattr fattr = {{0}};
        struct inode *inode = d_inode(path->dentry);
-       struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+       struct mnt_idmap *idmap = mnt_idmap(path->mnt);
+       struct user_namespace *user_ns = mnt_idmap_owner(idmap);
        struct iattr newattrs;
 
        fattr.cf_uid = INVALID_UID;
        }
 
        inode_lock(inode);
-       rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
+       rc = notify_change(idmap, path->dentry, &newattrs, NULL);
        inode_unlock(inode);
        if (rc)
                goto out;
 
        }
 
        mode |= S_IFREG;
-       err = vfs_create(mnt_user_ns(path.mnt), d_inode(path.dentry),
+       err = vfs_create(mnt_idmap(path.mnt), d_inode(path.dentry),
                         dentry, mode, true);
        if (!err) {
                ksmbd_vfs_inherit_owner(work, d_inode(path.dentry),
  */
 int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *user_ns;
        struct path path;
        struct dentry *dentry;
                return err;
        }
 
-       user_ns = mnt_user_ns(path.mnt);
+       idmap = mnt_idmap(path.mnt);
+       user_ns = mnt_idmap_owner(idmap);
        mode |= S_IFDIR;
-       err = vfs_mkdir(user_ns, d_inode(path.dentry), dentry, mode);
+       err = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode);
        if (err) {
                goto out;
        } else if (d_unhashed(dentry)) {
  */
 int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *user_ns;
        struct path path;
        struct dentry *parent;
                return err;
        }
 
-       user_ns = mnt_user_ns(path.mnt);
+       idmap = mnt_idmap(path.mnt);
+       user_ns = mnt_idmap_owner(idmap);
        parent = dget_parent(path.dentry);
        err = ksmbd_vfs_lock_parent(user_ns, parent, path.dentry);
        if (err) {
        }
 
        if (S_ISDIR(d_inode(path.dentry)->i_mode)) {
-               err = vfs_rmdir(user_ns, d_inode(parent), path.dentry);
+               err = vfs_rmdir(idmap, d_inode(parent), path.dentry);
                if (err && err != -ENOTEMPTY)
                        ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
                                    err);
        } else {
-               err = vfs_unlink(user_ns, d_inode(parent), path.dentry, NULL);
+               err = vfs_unlink(idmap, d_inode(parent), path.dentry, NULL);
                if (err)
                        ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
                                    err);
                goto out3;
        }
 
-       err = vfs_link(oldpath.dentry, mnt_user_ns(newpath.mnt),
+       err = vfs_link(oldpath.dentry, mnt_idmap(newpath.mnt),
                       d_inode(newpath.dentry),
                       dentry, NULL);
        if (err)
 }
 
 static int __ksmbd_vfs_rename(struct ksmbd_work *work,
-                             struct user_namespace *src_user_ns,
+                             struct mnt_idmap *src_idmap,
                              struct dentry *src_dent_parent,
                              struct dentry *src_dent,
-                             struct user_namespace *dst_user_ns,
+                             struct mnt_idmap *dst_idmap,
                              struct dentry *dst_dent_parent,
                              struct dentry *trap_dent,
                              char *dst_name)
        if (ksmbd_override_fsids(work))
                return -ENOMEM;
 
-       dst_dent = lookup_one(dst_user_ns, dst_name, dst_dent_parent,
-                             strlen(dst_name));
+       dst_dent = lookup_one(mnt_idmap_owner(dst_idmap), dst_name,
+                             dst_dent_parent, strlen(dst_name));
        err = PTR_ERR(dst_dent);
        if (IS_ERR(dst_dent)) {
                pr_err("lookup failed %s [%d]\n", dst_name, err);
        err = -ENOTEMPTY;
        if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
                struct renamedata rd = {
-                       .old_mnt_userns = src_user_ns,
+                       .old_mnt_idmap  = src_idmap,
                        .old_dir        = d_inode(src_dent_parent),
                        .old_dentry     = src_dent,
-                       .new_mnt_userns = dst_user_ns,
+                       .new_mnt_idmap  = dst_idmap,
                        .new_dir        = d_inode(dst_dent_parent),
                        .new_dentry     = dst_dent,
                };
 int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
                        char *newname)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *user_ns;
        struct path dst_path;
        struct dentry *src_dent_parent, *dst_dent_parent;
        trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
        dget(src_dent);
        dget(dst_dent_parent);
-       user_ns = file_mnt_user_ns(fp->filp);
+       idmap = file_mnt_idmap(fp->filp);
+       user_ns = mnt_idmap_owner(idmap);
        src_child = lookup_one(user_ns, src_dent->d_name.name, src_dent_parent,
                               src_dent->d_name.len);
        if (IS_ERR(src_child)) {
        dput(src_child);
 
        err = __ksmbd_vfs_rename(work,
-                                user_ns,
+                                idmap,
                                 src_dent_parent,
                                 src_dent,
-                                mnt_user_ns(dst_path.mnt),
+                                mnt_idmap(dst_path.mnt),
                                 dst_dent_parent,
                                 trap_dent,
                                 dst_name);
        return vfs_removexattr(user_ns, dentry, attr_name);
 }
 
-int ksmbd_vfs_unlink(struct user_namespace *user_ns,
+int ksmbd_vfs_unlink(struct mnt_idmap *idmap,
                     struct dentry *dir, struct dentry *dentry)
 {
        int err = 0;
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
 
-       err = ksmbd_vfs_lock_parent(user_ns, dir, dentry);
+       err = ksmbd_vfs_lock_parent(mnt_userns, dir, dentry);
        if (err)
                return err;
        dget(dentry);
 
        if (S_ISDIR(d_inode(dentry)->i_mode))
-               err = vfs_rmdir(user_ns, d_inode(dir), dentry);
+               err = vfs_rmdir(idmap, d_inode(dir), dentry);
        else
-               err = vfs_unlink(user_ns, d_inode(dir), dentry, NULL);
+               err = vfs_unlink(idmap, d_inode(dir), dentry, NULL);
 
        dput(dentry);
        inode_unlock(d_inode(dir));
 
 int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
                         struct file_allocated_range_buffer *ranges,
                         unsigned int in_count, unsigned int *out_count);
-int ksmbd_vfs_unlink(struct user_namespace *user_ns,
-                    struct dentry *dir, struct dentry *dentry);
+int ksmbd_vfs_unlink(struct mnt_idmap *idmap, struct dentry *dir,
+                    struct dentry *dentry);
 void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat);
 int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
                                struct user_namespace *user_ns,
 
                        dir = dentry->d_parent;
                        ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
                        write_unlock(&ci->m_lock);
-                       ksmbd_vfs_unlink(file_mnt_user_ns(filp), dir, dentry);
+                       ksmbd_vfs_unlink(file_mnt_idmap(filp), dir, dentry);
                        write_lock(&ci->m_lock);
                }
                write_unlock(&ci->m_lock);
 
 
 /**
  * vfs_create - create new file
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new file
  *
  * Create a new file.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then take
- * care to map the inode according to @mnt_userns before checking permissions.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_create(struct mnt_idmap *idmap, struct inode *dir,
               struct dentry *dentry, umode_t mode, bool want_excl)
 {
-       int error = may_create(mnt_userns, dir, dentry);
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
+       int error;
+
+       error = may_create(mnt_userns, dir, dentry);
        if (error)
                return error;
 
        return 0;
 }
 
-static int handle_truncate(struct user_namespace *mnt_userns, struct file *filp)
+static int handle_truncate(struct mnt_idmap *idmap, struct file *filp)
 {
        const struct path *path = &filp->f_path;
        struct inode *inode = path->dentry->d_inode;
 
        error = security_file_truncate(filp);
        if (!error) {
-               error = do_truncate(mnt_userns, path->dentry, 0,
+               error = do_truncate(idmap, path->dentry, 0,
                                    ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
                                    filp);
        }
 static int do_open(struct nameidata *nd,
                   struct file *file, const struct open_flags *op)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        int open_flag = op->open_flag;
        bool do_truncate;
        }
        if (!(file->f_mode & FMODE_CREATED))
                audit_inode(nd->name, nd->path.dentry, 0);
-       mnt_userns = mnt_user_ns(nd->path.mnt);
+       idmap = mnt_idmap(nd->path.mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        if (open_flag & O_CREAT) {
                if ((open_flag & O_EXCL) && !(file->f_mode & FMODE_CREATED))
                        return -EEXIST;
        if (!error)
                error = ima_file_check(file, op->acc_mode);
        if (!error && do_truncate)
-               error = handle_truncate(mnt_userns, file);
+               error = handle_truncate(idmap, file);
        if (unlikely(error > 0)) {
                WARN_ON(1);
                error = -EINVAL;
 
 /**
  * vfs_tmpfile - create tmpfile
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new tmpfile
  * @open_flag: flags
  *
  * Create a temporary file.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then take
- * care to map the inode according to @mnt_userns before checking permissions.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-static int vfs_tmpfile(struct user_namespace *mnt_userns,
+static int vfs_tmpfile(struct mnt_idmap *idmap,
                       const struct path *parentpath,
                       struct file *file, umode_t mode)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        struct dentry *child;
        struct inode *dir = d_inode(parentpath->dentry);
        struct inode *inode;
 
 /**
  * vfs_tmpfile_open - open a tmpfile for kernel internal use
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @parentpath:        path of the base directory
  * @mode:      mode of the new tmpfile
  * @open_flag: flags
  * hence this is only for kernel internal use, and must not be installed into
  * file tables or such.
  */
-struct file *vfs_tmpfile_open(struct user_namespace *mnt_userns,
+struct file *vfs_tmpfile_open(struct mnt_idmap *idmap,
                          const struct path *parentpath,
                          umode_t mode, int open_flag, const struct cred *cred)
 {
 
        file = alloc_empty_file_noaccount(open_flag, cred);
        if (!IS_ERR(file)) {
-               error = vfs_tmpfile(mnt_userns, parentpath, file, mode);
+               error = vfs_tmpfile(idmap, parentpath, file, mode);
                if (error) {
                        fput(file);
                        file = ERR_PTR(error);
                const struct open_flags *op,
                struct file *file)
 {
-       struct user_namespace *mnt_userns;
        struct path path;
        int error = path_lookupat(nd, flags | LOOKUP_DIRECTORY, &path);
 
        error = mnt_want_write(path.mnt);
        if (unlikely(error))
                goto out;
-       mnt_userns = mnt_user_ns(path.mnt);
-       error = vfs_tmpfile(mnt_userns, &path, file, op->mode);
+       error = vfs_tmpfile(mnt_idmap(path.mnt), &path, file, op->mode);
        if (error)
                goto out2;
        audit_inode(nd->name, file->f_path.dentry, 0);
 
 /**
  * vfs_mknod - create device node or file
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new device node or file
  *
  * Create a device node or file.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then take
- * care to map the inode according to @mnt_userns before checking permissions.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
              struct dentry *dentry, umode_t mode, dev_t dev)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV;
        int error = may_create(mnt_userns, dir, dentry);
 
 static int do_mknodat(int dfd, struct filename *name, umode_t mode,
                unsigned int dev)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        struct dentry *dentry;
        struct path path;
        if (error)
                goto out2;
 
-       mnt_userns = mnt_user_ns(path.mnt);
+       idmap = mnt_idmap(path.mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        switch (mode & S_IFMT) {
                case 0: case S_IFREG:
-                       error = vfs_create(mnt_userns, path.dentry->d_inode,
+                       error = vfs_create(idmap, path.dentry->d_inode,
                                           dentry, mode, true);
                        if (!error)
                                ima_post_path_mknod(mnt_userns, dentry);
                        break;
                case S_IFCHR: case S_IFBLK:
-                       error = vfs_mknod(mnt_userns, path.dentry->d_inode,
+                       error = vfs_mknod(idmap, path.dentry->d_inode,
                                          dentry, mode, new_decode_dev(dev));
                        break;
                case S_IFIFO: case S_IFSOCK:
-                       error = vfs_mknod(mnt_userns, path.dentry->d_inode,
+                       error = vfs_mknod(idmap, path.dentry->d_inode,
                                          dentry, mode, 0);
                        break;
        }
 
 /**
  * vfs_mkdir - create directory
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new directory
  *
  * Create a directory.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then take
- * care to map the inode according to @mnt_userns before checking permissions.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
              struct dentry *dentry, umode_t mode)
 {
-       int error = may_create(mnt_userns, dir, dentry);
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
+       int error;
        unsigned max_links = dir->i_sb->s_max_links;
 
+       error = may_create(mnt_userns, dir, dentry);
        if (error)
                return error;
 
        error = security_path_mkdir(&path, dentry,
                        mode_strip_umask(path.dentry->d_inode, mode));
        if (!error) {
-               struct user_namespace *mnt_userns;
-               mnt_userns = mnt_user_ns(path.mnt);
-               error = vfs_mkdir(mnt_userns, path.dentry->d_inode, dentry,
-                                 mode);
+               error = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
+                                 dentry, mode);
        }
        done_path_create(&path, dentry);
        if (retry_estale(error, lookup_flags)) {
 
 /**
  * vfs_rmdir - remove directory
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  *
  * Remove a directory.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then take
- * care to map the inode according to @mnt_userns before checking permissions.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_rmdir(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir,
                     struct dentry *dentry)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        int error = may_delete(mnt_userns, dir, dentry, 1);
 
        if (error)
 
 int do_rmdir(int dfd, struct filename *name)
 {
-       struct user_namespace *mnt_userns;
        int error;
        struct dentry *dentry;
        struct path path;
        error = security_path_rmdir(&path, dentry);
        if (error)
                goto exit4;
-       mnt_userns = mnt_user_ns(path.mnt);
-       error = vfs_rmdir(mnt_userns, path.dentry->d_inode, dentry);
+       error = vfs_rmdir(mnt_idmap(path.mnt), path.dentry->d_inode, dentry);
 exit4:
        dput(dentry);
 exit3:
 
 /**
  * vfs_unlink - unlink a filesystem object
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       parent directory
  * @dentry:    victim
  * @delegated_inode: returns victim inode, if the inode is delegated.
  * be appropriate for callers that expect the underlying filesystem not
  * to be NFS exported.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then take
- * care to map the inode according to @mnt_userns before checking permissions.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_unlink(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir,
               struct dentry *dentry, struct inode **delegated_inode)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        struct inode *target = dentry->d_inode;
        int error = may_delete(mnt_userns, dir, dentry, 0);
 
        dentry = __lookup_hash(&last, path.dentry, lookup_flags);
        error = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
-               struct user_namespace *mnt_userns;
 
                /* Why not before? Because we want correct error value */
                if (last.name[last.len])
                error = security_path_unlink(&path, dentry);
                if (error)
                        goto exit3;
-               mnt_userns = mnt_user_ns(path.mnt);
-               error = vfs_unlink(mnt_userns, path.dentry->d_inode, dentry,
-                                  &delegated_inode);
+               error = vfs_unlink(mnt_idmap(path.mnt), path.dentry->d_inode,
+                                  dentry, &delegated_inode);
 exit3:
                dput(dentry);
        }
 
 /**
  * vfs_symlink - create symlink
- * @mnt_userns:        user namespace of the mount the inode was found from
+ * @idmap:     idmap of the mount the inode was found from
  * @dir:       inode of @dentry
  * @dentry:    pointer to dentry of the base directory
  * @oldname:   name of the file to link to
  *
  * Create a symlink.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then take
- * care to map the inode according to @mnt_userns before checking permissions.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
+int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
                struct dentry *dentry, const char *oldname)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        int error = may_create(mnt_userns, dir, dentry);
 
        if (error)
                goto out_putnames;
 
        error = security_path_symlink(&path, dentry, from->name);
-       if (!error) {
-               struct user_namespace *mnt_userns;
-
-               mnt_userns = mnt_user_ns(path.mnt);
-               error = vfs_symlink(mnt_userns, path.dentry->d_inode, dentry,
-                                   from->name);
-       }
+       if (!error)
+               error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode,
+                                   dentry, from->name);
        done_path_create(&path, dentry);
        if (retry_estale(error, lookup_flags)) {
                lookup_flags |= LOOKUP_REVAL;
 /**
  * vfs_link - create a new link
  * @old_dentry:        object to be linked
- * @mnt_userns:        the user namespace of the mount
+ * @idmap:     idmap of the mount
  * @dir:       new parent
  * @new_dentry:        where to create the new link
  * @delegated_inode: returns inode needing a delegation break
  * be appropriate for callers that expect the underlying filesystem not
  * to be NFS exported.
  *
- * If the inode has been found through an idmapped mount the user namespace of
- * the vfsmount must be passed through @mnt_userns. This function will then take
- * care to map the inode according to @mnt_userns before checking permissions.
+ * If the inode has been found through an idmapped mount the idmap of
+ * the vfsmount must be passed through @idmap. This function will then take
+ * care to map the inode according to @idmap before checking permissions.
  * On non-idmapped mounts or if permission checking is to be performed on the
- * raw inode simply passs init_user_ns.
+ * raw inode simply passs @nop_mnt_idmap.
  */
-int vfs_link(struct dentry *old_dentry, struct user_namespace *mnt_userns,
+int vfs_link(struct dentry *old_dentry, struct mnt_idmap *idmap,
             struct inode *dir, struct dentry *new_dentry,
             struct inode **delegated_inode)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        struct inode *inode = old_dentry->d_inode;
        unsigned max_links = dir->i_sb->s_max_links;
        int error;
 int do_linkat(int olddfd, struct filename *old, int newdfd,
              struct filename *new, int flags)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        struct dentry *new_dentry;
        struct path old_path, new_path;
        error = -EXDEV;
        if (old_path.mnt != new_path.mnt)
                goto out_dput;
-       mnt_userns = mnt_user_ns(new_path.mnt);
+       idmap = mnt_idmap(new_path.mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        error = may_linkat(mnt_userns, &old_path);
        if (unlikely(error))
                goto out_dput;
        error = security_path_link(old_path.dentry, &new_path, new_dentry);
        if (error)
                goto out_dput;
-       error = vfs_link(old_path.dentry, mnt_userns, new_path.dentry->d_inode,
+       error = vfs_link(old_path.dentry, idmap, new_path.dentry->d_inode,
                         new_dentry, &delegated_inode);
 out_dput:
        done_path_create(&new_path, new_dentry);
        bool new_is_dir = false;
        unsigned max_links = new_dir->i_sb->s_max_links;
        struct name_snapshot old_name;
+       struct user_namespace *old_mnt_userns = mnt_idmap_owner(rd->old_mnt_idmap),
+                             *new_mnt_userns = mnt_idmap_owner(rd->new_mnt_idmap);
 
        if (source == target)
                return 0;
 
-       error = may_delete(rd->old_mnt_userns, old_dir, old_dentry, is_dir);
+       error = may_delete(old_mnt_userns, old_dir, old_dentry, is_dir);
        if (error)
                return error;
 
        if (!target) {
-               error = may_create(rd->new_mnt_userns, new_dir, new_dentry);
+               error = may_create(new_mnt_userns, new_dir, new_dentry);
        } else {
                new_is_dir = d_is_dir(new_dentry);
 
                if (!(flags & RENAME_EXCHANGE))
-                       error = may_delete(rd->new_mnt_userns, new_dir,
+                       error = may_delete(new_mnt_userns, new_dir,
                                           new_dentry, is_dir);
                else
-                       error = may_delete(rd->new_mnt_userns, new_dir,
+                       error = may_delete(new_mnt_userns, new_dir,
                                           new_dentry, new_is_dir);
        }
        if (error)
         */
        if (new_dir != old_dir) {
                if (is_dir) {
-                       error = inode_permission(rd->old_mnt_userns, source,
+                       error = inode_permission(old_mnt_userns, source,
                                                 MAY_WRITE);
                        if (error)
                                return error;
                }
                if ((flags & RENAME_EXCHANGE) && new_is_dir) {
-                       error = inode_permission(rd->new_mnt_userns, target,
+                       error = inode_permission(new_mnt_userns, target,
                                                 MAY_WRITE);
                        if (error)
                                return error;
                if (error)
                        goto out;
        }
-       error = old_dir->i_op->rename(rd->new_mnt_userns, old_dir, old_dentry,
+       error = old_dir->i_op->rename(new_mnt_userns, old_dir, old_dentry,
                                      new_dir, new_dentry, flags);
        if (error)
                goto out;
 
        rd.old_dir         = old_path.dentry->d_inode;
        rd.old_dentry      = old_dentry;
-       rd.old_mnt_userns  = mnt_user_ns(old_path.mnt);
+       rd.old_mnt_idmap   = mnt_idmap(old_path.mnt);
        rd.new_dir         = new_path.dentry->d_inode;
        rd.new_dentry      = new_dentry;
-       rd.new_mnt_userns  = mnt_user_ns(new_path.mnt);
+       rd.new_mnt_idmap   = mnt_idmap(new_path.mnt);
        rd.delegated_inode = &delegated_inode;
        rd.flags           = flags;
        error = vfs_rename(&rd);
 
                iap->ia_mode &= ~current_umask();
 
        fh_fill_pre_attrs(fhp);
-       host_err = vfs_create(&init_user_ns, inode, child, iap->ia_mode, true);
+       host_err = vfs_create(&nop_mnt_idmap, inode, child, iap->ia_mode, true);
        if (host_err < 0) {
                status = nfserrno(host_err);
                goto out;
 
                 * as well be forgiving and just succeed silently.
                 */
                goto out_put;
-       status = vfs_mkdir(&init_user_ns, d_inode(dir), dentry, S_IRWXU);
+       status = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, S_IRWXU);
 out_put:
        dput(dentry);
 out_unlock:
        status = -ENOENT;
        if (d_really_is_negative(dentry))
                goto out;
-       status = vfs_rmdir(&init_user_ns, d_inode(dir), dentry);
+       status = vfs_rmdir(&nop_mnt_idmap, d_inode(dir), dentry);
 out:
        dput(dentry);
 out_unlock:
        if (nfs4_has_reclaimed_state(name, nn))
                goto out_free;
 
-       status = vfs_rmdir(&init_user_ns, d_inode(parent), child);
+       status = vfs_rmdir(&nop_mnt_idmap, d_inode(parent), child);
        if (status)
                printk("failed to remove client recovery directory %pd\n",
                                child);
 
                if (iap->ia_size < 0)
                        return -EFBIG;
 
-               host_err = notify_change(&init_user_ns, dentry, &size_attr, NULL);
+               host_err = notify_change(&nop_mnt_idmap, dentry, &size_attr, NULL);
                if (host_err)
                        return host_err;
                iap->ia_valid &= ~ATTR_SIZE;
                return 0;
 
        iap->ia_valid |= ATTR_CTIME;
-       return notify_change(&init_user_ns, dentry, iap, NULL);
+       return notify_change(&nop_mnt_idmap, dentry, iap, NULL);
 }
 
 /**
        err = 0;
        switch (type) {
        case S_IFREG:
-               host_err = vfs_create(&init_user_ns, dirp, dchild, iap->ia_mode, true);
+               host_err = vfs_create(&nop_mnt_idmap, dirp, dchild,
+                                     iap->ia_mode, true);
                if (!host_err)
                        nfsd_check_ignore_resizing(iap);
                break;
        case S_IFDIR:
-               host_err = vfs_mkdir(&init_user_ns, dirp, dchild, iap->ia_mode);
+               host_err = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode);
                if (!host_err && unlikely(d_unhashed(dchild))) {
                        struct dentry *d;
                        d = lookup_one_len(dchild->d_name.name,
        case S_IFBLK:
        case S_IFIFO:
        case S_IFSOCK:
-               host_err = vfs_mknod(&init_user_ns, dirp, dchild,
+               host_err = vfs_mknod(&nop_mnt_idmap, dirp, dchild,
                                     iap->ia_mode, rdev);
                break;
        default:
                goto out_drop_write;
        }
        fh_fill_pre_attrs(fhp);
-       host_err = vfs_symlink(&init_user_ns, d_inode(dentry), dnew, path);
+       host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path);
        err = nfserrno(host_err);
        cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
        if (!err)
        if (d_really_is_negative(dold))
                goto out_dput;
        fh_fill_pre_attrs(ffhp);
-       host_err = vfs_link(dold, &init_user_ns, dirp, dnew, NULL);
+       host_err = vfs_link(dold, &nop_mnt_idmap, dirp, dnew, NULL);
        fh_fill_post_attrs(ffhp);
        inode_unlock(dirp);
        if (!host_err) {
                goto out_dput_old;
        } else {
                struct renamedata rd = {
-                       .old_mnt_userns = &init_user_ns,
+                       .old_mnt_idmap  = &nop_mnt_idmap,
                        .old_dir        = fdir,
                        .old_dentry     = odentry,
-                       .new_mnt_userns = &init_user_ns,
+                       .new_mnt_idmap  = &nop_mnt_idmap,
                        .new_dir        = tdir,
                        .new_dentry     = ndentry,
                };
                        nfsd_close_cached_files(rdentry);
 
                for (retries = 1;;) {
-                       host_err = vfs_unlink(&init_user_ns, dirp, rdentry, NULL);
+                       host_err = vfs_unlink(&nop_mnt_idmap, dirp, rdentry, NULL);
                        if (host_err != -EAGAIN || !retries--)
                                break;
                        if (!nfsd_wait_for_delegreturn(rqstp, rinode))
                                break;
                }
        } else {
-               host_err = vfs_rmdir(&init_user_ns, dirp, rdentry);
+               host_err = vfs_rmdir(&nop_mnt_idmap, dirp, rdentry);
        }
        fh_fill_post_attrs(fhp);
 
 
 
 #include "internal.h"
 
-int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
+int do_truncate(struct mnt_idmap *idmap, struct dentry *dentry,
                loff_t length, unsigned int time_attrs, struct file *filp)
 {
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        int ret;
        struct iattr newattrs;
 
 
        inode_lock(dentry->d_inode);
        /* Note any delegations or leases have already been broken: */
-       ret = notify_change(mnt_userns, dentry, &newattrs, NULL);
+       ret = notify_change(idmap, dentry, &newattrs, NULL);
        inode_unlock(dentry->d_inode);
        return ret;
 }
 
 long vfs_truncate(const struct path *path, loff_t length)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns;
        struct inode *inode;
        long error;
        if (error)
                goto out;
 
-       mnt_userns = mnt_user_ns(path->mnt);
+       idmap = mnt_idmap(path->mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        error = inode_permission(mnt_userns, inode, MAY_WRITE);
        if (error)
                goto mnt_drop_write_and_out;
 
        error = security_path_truncate(path);
        if (!error)
-               error = do_truncate(mnt_userns, path->dentry, length, 0, NULL);
+               error = do_truncate(idmap, path->dentry, length, 0, NULL);
 
 put_write_and_out:
        put_write_access(inode);
        sb_start_write(inode->i_sb);
        error = security_file_truncate(f.file);
        if (!error)
-               error = do_truncate(file_mnt_user_ns(f.file), dentry, length,
+               error = do_truncate(file_mnt_idmap(f.file), dentry, length,
                                    ATTR_MTIME | ATTR_CTIME, f.file);
        sb_end_write(inode->i_sb);
 out_putf:
                goto out_unlock;
        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-       error = notify_change(mnt_user_ns(path->mnt), path->dentry,
+       error = notify_change(mnt_idmap(path->mnt), path->dentry,
                              &newattrs, &delegated_inode);
 out_unlock:
        inode_unlock(inode);
 
 int chown_common(const struct path *path, uid_t user, gid_t group)
 {
+       struct mnt_idmap *idmap;
        struct user_namespace *mnt_userns, *fs_userns;
        struct inode *inode = path->dentry->d_inode;
        struct inode *delegated_inode = NULL;
        uid = make_kuid(current_user_ns(), user);
        gid = make_kgid(current_user_ns(), group);
 
-       mnt_userns = mnt_user_ns(path->mnt);
+       idmap = mnt_idmap(path->mnt);
+       mnt_userns = mnt_idmap_owner(idmap);
        fs_userns = i_user_ns(inode);
 
 retry_deleg:
                from_vfsuid(mnt_userns, fs_userns, newattrs.ia_vfsuid),
                from_vfsgid(mnt_userns, fs_userns, newattrs.ia_vfsgid));
        if (!error)
-               error = notify_change(mnt_userns, path->dentry, &newattrs,
+               error = notify_change(idmap, path->dentry, &newattrs,
                                      &delegated_inode);
        inode_unlock(inode);
        if (delegated_inode) {
        if (IS_ERR(f))
                return f;
 
-       error = vfs_create(mnt_user_ns(path->mnt),
+       error = vfs_create(mnt_idmap(path->mnt),
                           d_inode(path->dentry->d_parent),
                           path->dentry, mode, true);
        if (!error)
 
                                       struct dentry *upperdentry,
                                       struct iattr *attr)
 {
-       return notify_change(ovl_upper_mnt_userns(ofs), upperdentry, attr, NULL);
+       return notify_change(ovl_upper_mnt_idmap(ofs), upperdentry, attr, NULL);
 }
 
 static inline int ovl_do_rmdir(struct ovl_fs *ofs,
                               struct inode *dir, struct dentry *dentry)
 {
-       int err = vfs_rmdir(ovl_upper_mnt_userns(ofs), dir, dentry);
+       int err = vfs_rmdir(ovl_upper_mnt_idmap(ofs), dir, dentry);
 
        pr_debug("rmdir(%pd2) = %i\n", dentry, err);
        return err;
 static inline int ovl_do_unlink(struct ovl_fs *ofs, struct inode *dir,
                                struct dentry *dentry)
 {
-       int err = vfs_unlink(ovl_upper_mnt_userns(ofs), dir, dentry, NULL);
+       int err = vfs_unlink(ovl_upper_mnt_idmap(ofs), dir, dentry, NULL);
 
        pr_debug("unlink(%pd2) = %i\n", dentry, err);
        return err;
 static inline int ovl_do_link(struct ovl_fs *ofs, struct dentry *old_dentry,
                              struct inode *dir, struct dentry *new_dentry)
 {
-       int err = vfs_link(old_dentry, ovl_upper_mnt_userns(ofs), dir, new_dentry, NULL);
+       int err = vfs_link(old_dentry, ovl_upper_mnt_idmap(ofs), dir,
+                          new_dentry, NULL);
 
        pr_debug("link(%pd2, %pd2) = %i\n", old_dentry, new_dentry, err);
        return err;
                                struct inode *dir, struct dentry *dentry,
                                umode_t mode)
 {
-       int err = vfs_create(ovl_upper_mnt_userns(ofs), dir, dentry, mode, true);
+       int err = vfs_create(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, true);
 
        pr_debug("create(%pd2, 0%o) = %i\n", dentry, mode, err);
        return err;
                               struct inode *dir, struct dentry *dentry,
                               umode_t mode)
 {
-       int err = vfs_mkdir(ovl_upper_mnt_userns(ofs), dir, dentry, mode);
+       int err = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode);
        pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, err);
        return err;
 }
                               struct inode *dir, struct dentry *dentry,
                               umode_t mode, dev_t dev)
 {
-       int err = vfs_mknod(ovl_upper_mnt_userns(ofs), dir, dentry, mode, dev);
+       int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev);
 
        pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n", dentry, mode, dev, err);
        return err;
                                 struct inode *dir, struct dentry *dentry,
                                 const char *oldname)
 {
-       int err = vfs_symlink(ovl_upper_mnt_userns(ofs), dir, dentry, oldname);
+       int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname);
 
        pr_debug("symlink(\"%s\", %pd2) = %i\n", oldname, dentry, err);
        return err;
 {
        int err;
        struct renamedata rd = {
-               .old_mnt_userns = ovl_upper_mnt_userns(ofs),
+               .old_mnt_idmap  = ovl_upper_mnt_idmap(ofs),
                .old_dir        = olddir,
                .old_dentry     = olddentry,
-               .new_mnt_userns = ovl_upper_mnt_userns(ofs),
+               .new_mnt_idmap  = ovl_upper_mnt_idmap(ofs),
                .new_dir        = newdir,
                .new_dentry     = newdentry,
                .flags          = flags,
 static inline int ovl_do_whiteout(struct ovl_fs *ofs,
                                  struct inode *dir, struct dentry *dentry)
 {
-       int err = vfs_whiteout(ovl_upper_mnt_userns(ofs), dir, dentry);
+       int err = vfs_whiteout(ovl_upper_mnt_idmap(ofs), dir, dentry);
        pr_debug("whiteout(%pd2) = %i\n", dentry, err);
        return err;
 }
                                          struct dentry *dentry, umode_t mode)
 {
        struct path path = { .mnt = ovl_upper_mnt(ofs), .dentry = dentry };
-       struct file *file = vfs_tmpfile_open(ovl_upper_mnt_userns(ofs), &path, mode,
+       struct file *file = vfs_tmpfile_open(ovl_upper_mnt_idmap(ofs), &path, mode,
                                        O_LARGEFILE | O_WRONLY, current_cred());
        int err = PTR_ERR_OR_ZERO(file);
 
 
        return mnt_user_ns(ovl_upper_mnt(ofs));
 }
 
+static inline struct mnt_idmap *ovl_upper_mnt_idmap(struct ovl_fs *ofs)
+{
+       return mnt_idmap(ovl_upper_mnt(ofs));
+}
+
 static inline struct ovl_fs *OVL_FS(struct super_block *sb)
 {
        return (struct ovl_fs *)sb->s_fs_info;
 
        }
 retry_deleg:
        inode_lock(inode);
-       error = notify_change(mnt_user_ns(path->mnt), path->dentry, &newattrs,
+       error = notify_change(mnt_idmap(path->mnt), path->dentry, &newattrs,
                              &delegated_inode);
        inode_unlock(inode);
        if (delegated_inode) {
 
 /*
  * VFS helper functions..
  */
-int vfs_create(struct user_namespace *, struct inode *,
+int vfs_create(struct mnt_idmap *, struct inode *,
               struct dentry *, umode_t, bool);
-int vfs_mkdir(struct user_namespace *, struct inode *,
+int vfs_mkdir(struct mnt_idmap *, struct inode *,
              struct dentry *, umode_t);
-int vfs_mknod(struct user_namespace *, struct inode *, struct dentry *,
+int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
               umode_t, dev_t);
-int vfs_symlink(struct user_namespace *, struct inode *,
+int vfs_symlink(struct mnt_idmap *, struct inode *,
                struct dentry *, const char *);
-int vfs_link(struct dentry *, struct user_namespace *, struct inode *,
+int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *,
             struct dentry *, struct inode **);
-int vfs_rmdir(struct user_namespace *, struct inode *, struct dentry *);
-int vfs_unlink(struct user_namespace *, struct inode *, struct dentry *,
+int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *);
+int vfs_unlink(struct mnt_idmap *, struct inode *, struct dentry *,
               struct inode **);
 
 /**
  * struct renamedata - contains all information required for renaming
- * @old_mnt_userns:    old user namespace of the mount the inode was found from
+ * @old_mnt_idmap:     idmap of the old mount the inode was found from
  * @old_dir:           parent of source
  * @old_dentry:                source
- * @new_mnt_userns:    new user namespace of the mount the inode was found from
+ * @new_mnt_idmap:     idmap of the new mount the inode was found from
  * @new_dir:           parent of destination
  * @new_dentry:                destination
  * @delegated_inode:   returns an inode needing a delegation break
  * @flags:             rename flags
  */
 struct renamedata {
-       struct user_namespace *old_mnt_userns;
+       struct mnt_idmap *old_mnt_idmap;
        struct inode *old_dir;
        struct dentry *old_dentry;
-       struct user_namespace *new_mnt_userns;
+       struct mnt_idmap *new_mnt_idmap;
        struct inode *new_dir;
        struct dentry *new_dentry;
        struct inode **delegated_inode;
 
 int vfs_rename(struct renamedata *);
 
-static inline int vfs_whiteout(struct user_namespace *mnt_userns,
+static inline int vfs_whiteout(struct mnt_idmap *idmap,
                               struct inode *dir, struct dentry *dentry)
 {
-       return vfs_mknod(mnt_userns, dir, dentry, S_IFCHR | WHITEOUT_MODE,
+       return vfs_mknod(idmap, dir, dentry, S_IFCHR | WHITEOUT_MODE,
                         WHITEOUT_DEV);
 }
 
-struct file *vfs_tmpfile_open(struct user_namespace *mnt_userns,
+struct file *vfs_tmpfile_open(struct mnt_idmap *idmap,
                        const struct path *parentpath,
                        umode_t mode, int open_flag, const struct cred *cred);
 
 }
 
 extern long vfs_truncate(const struct path *, loff_t);
-int do_truncate(struct user_namespace *, struct dentry *, loff_t start,
+int do_truncate(struct mnt_idmap *, struct dentry *, loff_t start,
                unsigned int time_attrs, struct file *filp);
 extern int vfs_fallocate(struct file *file, int mode, loff_t offset,
                        loff_t len);
 }
 #endif
 
-int notify_change(struct user_namespace *, struct dentry *,
+int notify_change(struct mnt_idmap *, struct dentry *,
                  struct iattr *, struct inode **);
 int inode_permission(struct user_namespace *, struct inode *, int);
 int generic_permission(struct user_namespace *, struct inode *, int);
 
                err = -ENOENT;
        } else {
                ihold(inode);
-               err = vfs_unlink(&init_user_ns, d_inode(dentry->d_parent),
+               err = vfs_unlink(&nop_mnt_idmap, d_inode(dentry->d_parent),
                                 dentry, NULL);
        }
        dput(dentry);
 
        unsigned int new_hash, old_hash = sk->sk_hash;
        struct unix_sock *u = unix_sk(sk);
        struct net *net = sock_net(sk);
-       struct user_namespace *ns; // barf...
+       struct mnt_idmap *idmap;
        struct unix_address *addr;
        struct dentry *dentry;
        struct path parent;
        /*
         * All right, let's create it.
         */
-       ns = mnt_user_ns(parent.mnt);
+       idmap = mnt_idmap(parent.mnt);
        err = security_path_mknod(&parent, dentry, mode, 0);
        if (!err)
-               err = vfs_mknod(ns, d_inode(parent.dentry), dentry, mode, 0);
+               err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0);
        if (err)
                goto out_path;
        err = mutex_lock_interruptible(&u->bindlock);
        err = -EINVAL;
 out_unlink:
        /* failed after successful mknod?  unlink what we'd created... */
-       vfs_unlink(ns, d_inode(parent.dentry), dentry, NULL);
+       vfs_unlink(idmap, d_inode(parent.dentry), dentry, NULL);
 out_path:
        done_path_create(&parent, dentry);
 out:
 
 
 SEC("kprobe/vfs_link")
 int BPF_KPROBE(kprobe__vfs_link,
-              struct dentry* old_dentry, struct user_namespace *mnt_userns,
+              struct dentry* old_dentry, struct mnt_idmap *idmap,
               struct inode* dir, struct dentry* new_dentry,
               struct inode** delegated_inode)
 {