namespacefs: Add generic methods for idr printing

'idr' provides 'id to pointer' translation service avoiding the need of
fixed sized tables. Here we add generic helper methods for printing the
idr's content into synthetic files from sequences of records (seq_file).
The new definitions will be used by 'namespacefs' when printing the PIDs
of the tasks in each namespace.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
diff --git a/fs/namespacefs/inode.c b/fs/namespacefs/inode.c
index 07c3e9a..338694f 100644
--- a/fs/namespacefs/inode.c
+++ b/fs/namespacefs/inode.c
@@ -10,6 +10,8 @@
 #include <linux/namei.h>
 #include <linux/fsnotify.h>
 #include <linux/magic.h>
+#include <linux/idr.h>
+#include <linux/seq_file.h>
 
 #define S_IRALL (S_IRUSR | S_IRGRP | S_IROTH)
 #define S_IXALL (S_IXUSR | S_IXGRP | S_IXOTH)
@@ -179,6 +181,74 @@
 	_release_namespacefs();
 }
 
+struct idr_seq_context {
+	struct idr	*idr;
+	int		index;
+};
+
+static struct idr_seq_context *_alloc_idr_seq_context(struct idr *idr)
+{
+	struct idr_seq_context *idr_ctx = kzalloc(sizeof(*idr_ctx), GFP_KERNEL);
+
+	if (idr_ctx)
+		idr_ctx->idr = idr;
+	return idr_ctx;
+}
+
+static void *_idr_seq_get_next(struct idr_seq_context *idr_ctx, loff_t *pos)
+{
+	void *next = idr_get_next(idr_ctx->idr, &idr_ctx->index);
+
+	*pos = ++idr_ctx->index;
+	return next;
+}
+static void *idr_seq_start(struct seq_file *m, loff_t *pos)
+{
+	struct idr_seq_context *idr_ctx = m->private;
+
+	idr_lock(idr_ctx->idr);
+	idr_ctx->index = *pos;
+	return _idr_seq_get_next(idr_ctx, pos);
+}
+
+static void *idr_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	return _idr_seq_get_next(m->private, pos);
+}
+
+static void idr_seq_stop(struct seq_file *m, void *p)
+{
+	struct idr_seq_context *idr_ctx = m->private;
+
+	idr_unlock(idr_ctx->idr);
+}
+
+static int idr_seq_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *m = file->private_data;
+
+	kfree(m->private);
+	return seq_release(inode, file);
+}
+
+static int idr_seq_open(struct file *file, struct idr *idr,
+			const struct seq_operations *ops)
+{
+	struct seq_file *m;
+	int ret;
+
+	ret = seq_open(file, ops);
+	if (ret)
+		return ret;
+
+	m = file->private_data;
+	m->private = _alloc_idr_seq_context(idr);
+	if (!m->private)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int __init namespacefs_init(void)
 {
 	int err;
diff --git a/include/linux/idr-seq.h b/include/linux/idr-seq.h
deleted file mode 100644
index e69de29..0000000
--- a/include/linux/idr-seq.h
+++ /dev/null