Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754494AbZKEFh3 (ORCPT ); Thu, 5 Nov 2009 00:37:29 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751363AbZKEFh2 (ORCPT ); Thu, 5 Nov 2009 00:37:28 -0500 Received: from e33.co.us.ibm.com ([32.97.110.151]:56331 "EHLO e33.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751499AbZKEFh1 (ORCPT ); Thu, 5 Nov 2009 00:37:27 -0500 Date: Wed, 4 Nov 2009 21:38:15 -0800 From: Sukadev Bhattiprolu To: linux-kernel@vger.kernel.org Cc: arnd@arndb.de, Containers , "Eric W. Biederman" , hpa@zytor.com, Alexey Dobriyan , roland@redhat.com, Pavel Emelyanov , serue@us.ibm.com, Oren Laadan Subject: [v11][PATCH 3/9] Define set_pidmap() function Message-ID: <20091105053815.GC16142@us.ibm.com> References: <20091105053053.GA11289@us.ibm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20091105053053.GA11289@us.ibm.com> X-Operating-System: Linux 2.0.32 on an i486 User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3772 Lines: 122 From: Sukadev Bhattiprolu Subject: [v11][PATCH 3/9] Define set_pidmap() function Define a set_pidmap() interface which is like alloc_pidmap() only that caller specifies the pid number to be assigned. Changelog[v9]: - Completely rewrote this patch based on Eric Biederman's code. Changelog[v7]: - [Eric Biederman] Generalize alloc_pidmap() to take a range of pids. Changelog[v6]: - Separate target_pid > 0 case to minimize the number of checks needed. Changelog[v3]: - (Eric Biederman): Avoid set_pidmap() function. Added couple of checks for target_pid in alloc_pidmap() itself. Changelog[v2]: - (Serge Hallyn) Check for 'pid < 0' in set_pidmap().(Code actually checks for 'pid <= 0' for completeness). Signed-off-by: Sukadev Bhattiprolu Acked-by: Oren Laadan --- kernel/pid.c | 41 +++++++++++++++++++++++++++++++++-------- 1 files changed, 33 insertions(+), 8 deletions(-) diff --git a/kernel/pid.c b/kernel/pid.c index c4d9914..c849327 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -147,18 +147,19 @@ static int alloc_pidmap_page(struct pidmap *map) return 0; } -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; int rc = -EAGAIN; struct pidmap *map; pid = last + 1; if (pid >= pid_max) - pid = RESERVED_PIDS; + 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) { rc = alloc_pidmap_page(map); if (rc) @@ -168,7 +169,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); @@ -179,16 +179,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)) { rc = -EAGAIN; break; @@ -199,6 +199,31 @@ static int alloc_pidmap(struct pid_namespace *pid_ns) return rc; } +static int alloc_pidmap(struct pid_namespace *pid_ns) +{ + int nr; + + nr = do_alloc_pidmap(pid_ns, pid_ns->last_pid, 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) + return alloc_pidmap(pid_ns); + + if (target >= pid_max) + return -EINVAL; + + if ((target < 0) || (target < RESERVED_PIDS && + pid_ns->last_pid >= RESERVED_PIDS)) + return -EINVAL; + + return do_alloc_pidmap(pid_ns, target - 1, target, target + 1); +} + int next_pidmap(struct pid_namespace *pid_ns, int last) { int offset; -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/