From the previous post that contained the exhaustive list of the functions that need replacing/deleting[can be read here], I will list a few of the changes I made here. You will be able to see how and why using the IDR API is more effective as far the reducing the kernel size is concerned.

A few examples of how IDR is helping in reducing the size of the kernel:

static void destroy_pid_namespace(struct pid_namespace *ns)
{
- int i;
-
ns_free_inum(&ns->ns);
- for (i = 0; i < PIDMAP_ENTRIES; i++)
- kfree(ns->pidmap[i].page);
+
+ idr_destroy(ns->idr);
call_rcu(&ns->rcu, delayed_free_pidns);
}

Instead of individually removing pages from pidmap, we can simply destroy the idr struct associated with that namespace.

Inside the find_ge_pid() function, where we want to find the next greatest pid, earlier we used to traverse the pages in the pidmap to see if there is an allocated integer in the map, now a simple call to idr_get_next() would suffice.

struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
{
- struct pid *pid;
-
- do {
- pid = find_pid_ns(nr, ns);
- if (pid)
- break;
- nr = next_pidmap(ns, nr);
- } while (nr > 0);
-
- return pid;
+ return idr_get_next(ns->idr, &nr);
}

We also got rid of functions like alloc_pidmap(), free_pidmap() etc. which managed the pidmap and allocations of the pages. IDR takes away this complexity by exposing the API which takes care of all of this.

In theory, using IDR should also be faster, since pidmap is linear time whereas IDR should be log time in the worst case. If this will be true in practice is something to be figured out as the next step.

As for now, here are the size metrics before and after IDR implementation. The kernel size seems to have shrunk nicely! :D