From patchwork Thu Nov 5 20:07:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 540691 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 0625A1413D3 for ; Fri, 6 Nov 2015 07:08:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752928AbbKEUH7 (ORCPT ); Thu, 5 Nov 2015 15:07:59 -0500 Received: from aserp1040.oracle.com ([141.146.126.69]:32630 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750749AbbKEUH6 (ORCPT ); Thu, 5 Nov 2015 15:07:58 -0500 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id tA5K7qpA008624 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 5 Nov 2015 20:07:53 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id tA5K7qaI024126 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 5 Nov 2015 20:07:52 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id tA5K7pC5010087; Thu, 5 Nov 2015 20:07:51 GMT Received: from lappy.us.oracle.com (/10.154.118.243) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 05 Nov 2015 12:07:51 -0800 From: Sasha Levin To: xeb@mail.ru Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sasha Levin Subject: [PATCH] pptp: use idr for allocation of callids Date: Thu, 5 Nov 2015 15:07:44 -0500 Message-Id: <1446754064-1195-1-git-send-email-sasha.levin@oracle.com> X-Mailer: git-send-email 2.5.0 X-Source-IP: aserv0022.oracle.com [141.146.126.234] Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The current implementation used a bitfield with a corresponding array to manage assignment of call ids. Rather than open-coding it, use IDR for this. Signed-off-by: Sasha Levin --- drivers/net/ppp/pptp.c | 67 +++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index fc69e41..4637314 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -43,10 +44,7 @@ #define PPTP_DRIVER_VERSION "0.8.5" #define MAX_CALLID 65535 - -static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1); -static struct pppox_sock __rcu **callid_sock; - +static struct idr callid; static DEFINE_SPINLOCK(chan_lock); static struct proto pptp_sk_proto __read_mostly; @@ -94,7 +92,7 @@ static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr) struct pptp_opt *opt; rcu_read_lock(); - sock = rcu_dereference(callid_sock[call_id]); + sock = idr_find(&callid, call_id); if (sock) { opt = &sock->proto.pptp; if (opt->dst_addr.sin_addr.s_addr != s_addr) @@ -107,60 +105,55 @@ static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr) return sock; } -static int lookup_chan_dst(u16 call_id, __be32 d_addr) +static bool lookup_chan_dst(u16 call_id, __be32 d_addr) { struct pppox_sock *sock; struct pptp_opt *opt; int i; + bool found = false; rcu_read_lock(); - i = 1; - for_each_set_bit_from(i, callid_bitmap, MAX_CALLID) { - sock = rcu_dereference(callid_sock[i]); - if (!sock) - continue; + idr_for_each_entry(&callid, sock, i) { opt = &sock->proto.pptp; if (opt->dst_addr.call_id == call_id && - opt->dst_addr.sin_addr.s_addr == d_addr) + opt->dst_addr.sin_addr.s_addr == d_addr) { + found = true; break; + } } rcu_read_unlock(); - return i < MAX_CALLID; + return found; } static int add_chan(struct pppox_sock *sock) { - static int call_id; + int ret, requested; - spin_lock(&chan_lock); - if (!sock->proto.pptp.src_addr.call_id) { - call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1); - if (call_id == MAX_CALLID) { - call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1); - if (call_id == MAX_CALLID) - goto out_err; - } - sock->proto.pptp.src_addr.call_id = call_id; - } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap)) - goto out_err; + idr_preload(GFP_KERNEL); - set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); - rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock); + spin_lock(&chan_lock); + requested = sock->proto.pptp.src_addr.call_id; + if (!requested) + ret = idr_alloc(&callid, sock, 1, MAX_CALLID, GFP_ATOMIC); + else + ret = idr_alloc(&callid, sock, requested, requested + 1, GFP_ATOMIC); spin_unlock(&chan_lock); - return 0; + idr_preload_end(); -out_err: - spin_unlock(&chan_lock); - return -1; + return ret; } static void del_chan(struct pppox_sock *sock) { spin_lock(&chan_lock); - clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); - RCU_INIT_POINTER(callid_sock[sock->proto.pptp.src_addr.call_id], NULL); + /* + * It's possible the sock was created but never bound, let's verify + * that this isn't the case before blindly deleting a different sock. + */ + if (idr_find(&callid, sock->proto.pptp.src_addr.call_id) == sock) + idr_remove(&callid, sock->proto.pptp.src_addr.call_id); spin_unlock(&chan_lock); synchronize_rcu(); } @@ -670,9 +663,7 @@ static int __init pptp_init_module(void) int err = 0; pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n"); - callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *)); - if (!callid_sock) - return -ENOMEM; + idr_init(&callid); err = gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP); if (err) { @@ -699,7 +690,7 @@ out_unregister_sk_proto: out_gre_del_protocol: gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP); out_mem_free: - vfree(callid_sock); + idr_destroy(&callid); return err; } @@ -709,7 +700,7 @@ static void __exit pptp_exit_module(void) unregister_pppox_proto(PX_PROTO_PPTP); proto_unregister(&pptp_sk_proto); gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP); - vfree(callid_sock); + idr_destroy(&callid); } module_init(pptp_init_module);