struct mnt_idmap is immutable once alloc_mnt_idmap() has set it up. The
only thing that changes afterwards is the reference count. Model
mnt_idmap_{get,put}() after struct cred's reference count handling and
take a const pointer.

This model is forced upon us because ceph stores the idmapping in mds
requests and need to be able to take and put references.

mnt_idmap_get() keeps returning a non-const pointer for now because
struct vfsmount still stores a non-const pointer. We can only change
that at the end of the series once every user of mnt_idmap() has been
ported.

Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
 fs/internal.h                 |  4 ++--
 fs/mnt_idmapping.c            | 16 ++++++++++------
 include/linux/mnt_idmapping.h |  4 ++--
 3 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index c658c8a5ebd5..581aaa2d6510 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -327,8 +327,8 @@ ssize_t __kernel_write_iter(struct file *file, struct 
iov_iter *from, loff_t *po
  * fs/attr.c
  */
 struct mnt_idmap *alloc_mnt_idmap(struct user_namespace *mnt_userns);
-struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap);
-void mnt_idmap_put(struct mnt_idmap *idmap);
+struct mnt_idmap *mnt_idmap_get(const struct mnt_idmap *idmap);
+void mnt_idmap_put(const struct mnt_idmap *idmap);
 struct stashed_operations {
        struct dentry *(*stash_dentry)(struct dentry **stashed,
                                       struct dentry *dentry);
diff --git a/fs/mnt_idmapping.c b/fs/mnt_idmapping.c
index cb61fbdb52e9..cc6c5f1cfba8 100644
--- a/fs/mnt_idmapping.c
+++ b/fs/mnt_idmapping.c
@@ -312,12 +312,14 @@ struct mnt_idmap *alloc_mnt_idmap(struct user_namespace 
*mnt_userns)
  *
  * Return: @idmap with reference count bumped if @not_mnt_idmap isn't passed.
  */
-struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap)
+struct mnt_idmap *mnt_idmap_get(const struct mnt_idmap *idmap)
 {
+       struct mnt_idmap *nonconst_idmap = (struct mnt_idmap *)idmap;
+
        if (idmap != &nop_mnt_idmap && idmap != &invalid_mnt_idmap)
-               refcount_inc(&idmap->count);
+               refcount_inc(&nonconst_idmap->count);
 
-       return idmap;
+       return nonconst_idmap;
 }
 EXPORT_SYMBOL_GPL(mnt_idmap_get);
 
@@ -328,11 +330,13 @@ EXPORT_SYMBOL_GPL(mnt_idmap_get);
  * If this is a non-initial idmapping, put the reference count when a mount is
  * released and free it if we're the last user.
  */
-void mnt_idmap_put(struct mnt_idmap *idmap)
+void mnt_idmap_put(const struct mnt_idmap *idmap)
 {
+       struct mnt_idmap *nonconst_idmap = (struct mnt_idmap *)idmap;
+
        if (idmap != &nop_mnt_idmap && idmap != &invalid_mnt_idmap &&
-           refcount_dec_and_test(&idmap->count))
-               free_mnt_idmap(idmap);
+           refcount_dec_and_test(&nonconst_idmap->count))
+               free_mnt_idmap(nonconst_idmap);
 }
 EXPORT_SYMBOL_GPL(mnt_idmap_put);
 
diff --git a/include/linux/mnt_idmapping.h b/include/linux/mnt_idmapping.h
index e71a6070a8f8..e5bee8b41094 100644
--- a/include/linux/mnt_idmapping.h
+++ b/include/linux/mnt_idmapping.h
@@ -121,8 +121,8 @@ static inline bool vfsgid_eq_kgid(vfsgid_t vfsgid, kgid_t 
kgid)
 
 int vfsgid_in_group_p(vfsgid_t vfsgid);
 
-struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap);
-void mnt_idmap_put(struct mnt_idmap *idmap);
+struct mnt_idmap *mnt_idmap_get(const struct mnt_idmap *idmap);
+void mnt_idmap_put(const struct mnt_idmap *idmap);
 
 vfsuid_t make_vfsuid(struct mnt_idmap *idmap,
                     struct user_namespace *fs_userns, kuid_t kuid);

-- 
2.53.0


Reply via email to