[PATCH V7 02/10] nsfs: switch to dedicated inode pool

Richard Guy Briggs rgb at redhat.com
Tue May 12 20:02:39 UTC 2015


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 <rgb at redhat.com>
---
 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




More information about the Linux-audit mailing list