Re: /proc/sys/kernel/pid_max issues

From: Ingo Molnar
Date: Sun Sep 12 2004 - 05:17:26 EST



* William Lee Irwin III <wli@xxxxxxxxxxxxxx> wrote:

> If pid_max == BITS_PER_PAGE*n, none of
> &pidmap_array[pid_max/BITS_PER_PAGE] is usable, so if we must complete
> a full revolution around pidmap_array[] to discover a free pid
> slightly less than last_pid we will miss it. Hence:

yeah. Patch needs testing ...

> if (++map == map_limit)
> map = pidmap_array;
> + if (map > &pidmap_array[(pid_max-1)/BITS_PER_PAGE])
> + map = pidmap_array;

in fact we can now merge the max_limit and pid_max checks - see the
attached updated patch.

Ingo

fix pid_max handling. Wrap around correctly.

Signed-off-by: William Lee Irwin III <wli@xxxxxxxxxxxxxx>
Signed-off-by: Ingo Molnar <mingo@xxxxxxx>

--- linux/kernel/pid.c.orig
+++ linux/kernel/pid.c
@@ -53,8 +53,6 @@ typedef struct pidmap {
static pidmap_t pidmap_array[PIDMAP_ENTRIES] =
{ [ 0 ... PIDMAP_ENTRIES-1 ] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } };

-static pidmap_t *map_limit = pidmap_array + PIDMAP_ENTRIES;
-
static spinlock_t pidmap_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;

fastcall void free_pidmap(int pid)
@@ -73,7 +71,9 @@ fastcall void free_pidmap(int pid)
static inline pidmap_t *next_free_map(pidmap_t *map, int *max_steps)
{
while (--*max_steps) {
- if (++map == map_limit)
+ pidmap_t *map_limit = pidmap_array + (pid_max-1)/BITS_PER_PAGE;
+
+ if (++map > map_limit)
map = pidmap_array;
if (unlikely(!map->page)) {
unsigned long page = get_zeroed_page(GFP_KERNEL);
@@ -133,13 +133,12 @@ next_map:
*/
scan_more:
offset = find_next_zero_bit(map->page, BITS_PER_PAGE, offset);
- if (offset >= BITS_PER_PAGE)
+ pid = (map - pidmap_array) * BITS_PER_PAGE + offset;
+ if (offset >= BITS_PER_PAGE || pid >= pid_max)
goto next_map;
if (test_and_set_bit(offset, map->page))
goto scan_more;
-
/* we got the PID: */
- pid = (map - pidmap_array) * BITS_PER_PAGE + offset;
goto return_pid;

failure: