Instead of borrowing proc's inode pool and starting at a custom offset, give
nsfs its own dedicated inode pool without an offset.

Signed-off-by: Richard Guy Briggs <[email protected]>
---
 fs/nsfs.c               |   44 ++++++++++++++++++++++++++++++++++++++++++++
 fs/proc/internal.h      |    2 ++
 include/linux/proc_ns.h |   20 ++++++++------------
 init/version.c          |    2 +-
 ipc/msgutil.c           |    2 +-
 kernel/pid.c            |    2 +-
 kernel/user.c           |    2 +-
 7 files changed, 58 insertions(+), 16 deletions(-)

diff --git a/fs/nsfs.c b/fs/nsfs.c
index af1b24f..1fcd529 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -159,3 +159,47 @@ void __init nsfs_init(void)
                panic("can't set nsfs up\n");
        nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER;
 }
+
+static DEFINE_IDA(ns_inum_ida);
+static DEFINE_SPINLOCK(ns_inum_lock); /* protects the above */
+
+/*
+ * Return an inode number between PROC_DYNAMIC_FIRST and
+ * 0xffffffff, or zero on failure.
+ */
+int ns_alloc_inum(struct ns_common *ns)
+{
+       unsigned int i;
+       int error;
+
+       atomic_long_set(&ns->stashed, 0);
+retry:
+       if (!ida_pre_get(&ns_inum_ida, GFP_KERNEL))
+               return -ENOMEM;
+
+       spin_lock_irq(&ns_inum_lock);
+       error = ida_get_new(&ns_inum_ida, &i);
+       spin_unlock_irq(&ns_inum_lock);
+       if (error == -EAGAIN)
+               goto retry;
+       else if (error)
+               return error;
+
+       if (i > UINT_MAX) {
+               spin_lock_irq(&ns_inum_lock);
+               ida_remove(&ns_inum_ida, i);
+               spin_unlock_irq(&ns_inum_lock);
+               return -ENOSPC;
+       }
+       ns->inum = NS_DYNAMIC_FIRST + i;
+       return 0;
+}
+
+void ns_free_inum(struct ns_common *ns)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&ns_inum_lock, flags);
+       ida_remove(&ns_inum_ida, ns->inum - NS_DYNAMIC_FIRST);
+       spin_unlock_irqrestore(&ns_inum_lock, flags);
+}
+
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index c835b94..8f89cbb 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -18,6 +18,8 @@
 struct ctl_table_header;
 struct mempolicy;
 
+#define PROC_ROOT_INO 1
+
 /*
  * This is not completely implemented yet. The idea is to
  * create an in-memory tree (like the actual /proc filesystem
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
index 2654550..721d0e2 100644
--- a/include/linux/proc_ns.h
+++ b/include/linux/proc_ns.h
@@ -30,11 +30,12 @@ extern const struct proc_ns_operations *ns_entries[];
  * We always define these enumerators
  */
 enum {
-       PROC_ROOT_INO           = 1,
-       PROC_IPC_INIT_INO       = 0xEFFFFFFFU,
-       PROC_UTS_INIT_INO       = 0xEFFFFFFEU,
-       PROC_USER_INIT_INO      = 0xEFFFFFFDU,
-       PROC_PID_INIT_INO       = 0xEFFFFFFCU,
+       NS_NULL_INIT_INO,
+       NS_IPC_INIT_INO,
+       NS_UTS_INIT_INO,
+       NS_USER_INIT_INO,
+       NS_PID_INIT_INO,
+       NS_DYNAMIC_FIRST,
 };
 
 #ifdef CONFIG_PROC_FS
@@ -58,13 +59,8 @@ static inline void proc_free_inum(unsigned int inum) {}
 
 #endif /* CONFIG_PROC_FS */
 
-static inline int ns_alloc_inum(struct ns_common *ns)
-{
-       atomic_long_set(&ns->stashed, 0);
-       return proc_alloc_inum(&ns->inum);
-}
-
-#define ns_free_inum(ns) proc_free_inum((ns)->inum)
+extern int ns_alloc_inum(struct ns_common *ns);
+extern void ns_free_inum(struct ns_common *ns);
 
 extern struct file *proc_ns_fget(int fd);
 #define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
diff --git a/init/version.c b/init/version.c
index fe41a63..050dda0 100644
--- a/init/version.c
+++ b/init/version.c
@@ -35,7 +35,7 @@ struct uts_namespace init_uts_ns = {
                .domainname     = UTS_DOMAINNAME,
        },
        .user_ns = &init_user_ns,
-       .ns.inum = PROC_UTS_INIT_INO,
+       .ns.inum = NS_UTS_INIT_INO,
 #ifdef CONFIG_UTS_NS
        .ns.ops = &utsns_operations,
 #endif
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 2b49159..aca24bb 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -31,7 +31,7 @@ DEFINE_SPINLOCK(mq_lock);
 struct ipc_namespace init_ipc_ns = {
        .count          = ATOMIC_INIT(1),
        .user_ns = &init_user_ns,
-       .ns.inum = PROC_IPC_INIT_INO,
+       .ns.inum = NS_IPC_INIT_INO,
 #ifdef CONFIG_IPC_NS
        .ns.ops = &ipcns_operations,
 #endif
diff --git a/kernel/pid.c b/kernel/pid.c
index cd36a5e..a06abc2 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -79,7 +79,7 @@ struct pid_namespace init_pid_ns = {
        .level = 0,
        .child_reaper = &init_task,
        .user_ns = &init_user_ns,
-       .ns.inum = PROC_PID_INIT_INO,
+       .ns.inum = NS_PID_INIT_INO,
 #ifdef CONFIG_PID_NS
        .ns.ops = &pidns_operations,
 #endif
diff --git a/kernel/user.c b/kernel/user.c
index b069ccb..deaf107 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -50,7 +50,7 @@ struct user_namespace init_user_ns = {
        .count = ATOMIC_INIT(3),
        .owner = GLOBAL_ROOT_UID,
        .group = GLOBAL_ROOT_GID,
-       .ns.inum = PROC_USER_INIT_INO,
+       .ns.inum = NS_USER_INIT_INO,
 #ifdef CONFIG_USER_NS
        .ns.ops = &userns_operations,
 #endif
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to