Sukadev Bhattiprolu <[email protected]> writes:

> Eric W. Biederman [[email protected]] wrote:
> | > I will post a version of the patch outside this patchset with min
> | > and max parameters and we can see if it can be optimized/beautified.
> | 
> | Thanks,
> | Eric
>
> Here is the patch.  alloc_pid() calls alloc_pidmap() as follows:
>
> -             nr = alloc_pidmap(tmp);
> +             min = max = 0;
> +             if (target_pids) {
> +                     min = target_pids[i];
> +                     max = min + 1;
> +             }
> +             nr = alloc_pidmap(tmp, min, max);
>
> It does look like this patch executes a bit more code even in the common
> case but let me know if you think this is better.
>       
> ---

Not what I was thinking.  The following untested patch is what I was
thinking.  It just exposes last, min, and max to the callers which pass
in different appropriate values.

Eric

diff --git a/kernel/pid.c b/kernel/pid.c
index d3f722d..d9b6f82 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -122,17 +122,17 @@ static void free_pidmap(struct upid *upid)
        atomic_inc(&map->nr_free);
 }
 
-static int alloc_pidmap(struct pid_namespace *pid_ns)
+static int do_alloc_pidmap(struct pid_namespace *pid_ns, int last, int min, 
int max)
 {
-       int i, offset, max_scan, pid, last = pid_ns->last_pid;
+       int i, offset, max_scan, pid;
        struct pidmap *map;
 
        pid = last + 1;
-       if (pid >= pid_max)
-               pid = RESERVED_PIDS;
+       if (pid >= max)
+               pid = min;
        offset = pid & BITS_PER_PAGE_MASK;
        map = &pid_ns->pidmap[pid/BITS_PER_PAGE];
-       max_scan = (pid_max + BITS_PER_PAGE - 1)/BITS_PER_PAGE - !offset;
+       max_scan = (max + BITS_PER_PAGE - 1)/BITS_PER_PAGE - !offset;
        for (i = 0; i <= max_scan; ++i) {
                if (unlikely(!map->page)) {
                        void *page = kzalloc(PAGE_SIZE, GFP_KERNEL);
@@ -153,7 +153,6 @@ static int alloc_pidmap(struct pid_namespace *pid_ns)
                        do {
                                if (!test_and_set_bit(offset, map->page)) {
                                        atomic_dec(&map->nr_free);
-                                       pid_ns->last_pid = pid;
                                        return pid;
                                }
                                offset = find_next_offset(map, offset);
@@ -164,16 +163,16 @@ static int alloc_pidmap(struct pid_namespace *pid_ns)
                         * bitmap block and the final block was the same
                         * as the starting point, pid is before last_pid.
                         */
-                       } while (offset < BITS_PER_PAGE && pid < pid_max &&
+                       } while (offset < BITS_PER_PAGE && pid < max &&
                                        (i != max_scan || pid < last ||
                                            !((last+1) & BITS_PER_PAGE_MASK)));
                }
-               if (map < &pid_ns->pidmap[(pid_max-1)/BITS_PER_PAGE]) {
+               if (map < &pid_ns->pidmap[(max-1)/BITS_PER_PAGE]) {
                        ++map;
                        offset = 0;
                } else {
                        map = &pid_ns->pidmap[0];
-                       offset = RESERVED_PIDS;
+                       offset = min;
                        if (unlikely(last == offset))
                                break;
                }
@@ -182,6 +181,25 @@ static int alloc_pidmap(struct pid_namespace *pid_ns)
        return -1;
 }
 
+static int alloc_pidmap(struct pid_namespace *pid_ns)
+{
+       int nr;
+
+       nr = do_alloc_pidmap(pid_ns, pid_ns->last, RESERVED_PIDS, pid_max);
+       if (nr >= 0)
+               pid_ns->last_pid = nr;
+       return nr;
+}
+
+static int set_pidmap(struct pid_namespace *pid_ns, int target)
+{
+       if (target >= pid_max)
+               return -1;
+       if (target < RESERVED_PIDS)
+               return -1;
+       return do_alloc_pidmap(pid_ns, target - 1, target, target + 1);
+}
+
 int next_pidmap(struct pid_namespace *pid_ns, int last)
 {
        int offset;
--
To unsubscribe from this list: send the line "unsubscribe linux-api" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to