From patchwork Fri Nov 13 15:01:19 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= X-Patchwork-Id: 38371 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.176.167]) by ozlabs.org (Postfix) with ESMTP id 1332AB7B60 for ; Sat, 14 Nov 2009 02:01:27 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755666AbZKMPBQ (ORCPT ); Fri, 13 Nov 2009 10:01:16 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755575AbZKMPBP (ORCPT ); Fri, 13 Nov 2009 10:01:15 -0500 Received: from yop.chewa.net ([91.121.105.214]:42996 "EHLO yop.chewa.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754986AbZKMPBO (ORCPT ); Fri, 13 Nov 2009 10:01:14 -0500 Received: by yop.chewa.net (Postfix, from userid 1007) id 114492AD; Fri, 13 Nov 2009 16:01:19 +0100 (CET) From: =?utf-8?q?R=C3=A9mi=20Denis-Courmont?= To: netdev@vger.kernel.org Cc: =?utf-8?q?R=C3=A9mi=20Denis-Courmont?= Subject: [PATCH net-next 2/2] Phonet: convert routing table to RCU Date: Fri, 13 Nov 2009 17:01:19 +0200 Message-Id: <1258124479-1167-2-git-send-email-remi@remlab.net> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: <1258124479-1167-1-git-send-email-remi@remlab.net> References: <1258124479-1167-1-git-send-email-remi@remlab.net> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Rémi Denis-Courmont Signed-off-by: Rémi Denis-Courmont --- net/phonet/pn_dev.c | 59 +++++++++++++++++++++++++++++--------------------- 1 files changed, 34 insertions(+), 25 deletions(-) diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 6d64fda..3287f8f 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -34,7 +34,7 @@ #include struct phonet_routes { - spinlock_t lock; + struct mutex lock; struct net_device *table[64]; }; @@ -248,17 +248,22 @@ static void phonet_route_autodel(struct net_device *dev) /* Remove left-over Phonet routes */ bitmap_zero(deleted, 64); - spin_lock_bh(&pnn->routes.lock); + mutex_lock(&pnn->routes.lock); for (i = 0; i < 64; i++) if (dev == pnn->routes.table[i]) { + rcu_assign_pointer(pnn->routes.table[i], NULL); set_bit(i, deleted); - pnn->routes.table[i] = NULL; - dev_put(dev); } - spin_unlock_bh(&pnn->routes.lock); + mutex_unlock(&pnn->routes.lock); + + if (bitmap_empty(deleted, 64)) + return; /* short-circuit RCU */ + synchronize_rcu(); for (i = find_first_bit(deleted, 64); i < 64; - i = find_next_bit(deleted, 64, i + 1)) + i = find_next_bit(deleted, 64, i + 1)) { rtm_phonet_notify(RTM_DELROUTE, dev, i); + dev_put(dev); + } } /* notify Phonet of device events */ @@ -300,7 +305,7 @@ static int phonet_init_net(struct net *net) INIT_LIST_HEAD(&pnn->pndevs.list); spin_lock_init(&pnn->pndevs.lock); - spin_lock_init(&pnn->routes.lock); + mutex_init(&pnn->routes.lock); net_assign_generic(net, phonet_net_id, pnn); return 0; } @@ -361,13 +366,13 @@ int phonet_route_add(struct net_device *dev, u8 daddr) int err = -EEXIST; daddr = daddr >> 2; - spin_lock_bh(&routes->lock); + mutex_lock(&routes->lock); if (routes->table[daddr] == NULL) { - routes->table[daddr] = dev; + rcu_assign_pointer(routes->table[daddr], dev); dev_hold(dev); err = 0; } - spin_unlock_bh(&routes->lock); + mutex_unlock(&routes->lock); return err; } @@ -375,17 +380,20 @@ int phonet_route_del(struct net_device *dev, u8 daddr) { struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); struct phonet_routes *routes = &pnn->routes; - int err = -ENOENT; daddr = daddr >> 2; - spin_lock_bh(&routes->lock); - if (dev == routes->table[daddr]) { - routes->table[daddr] = NULL; - dev_put(dev); - err = 0; - } - spin_unlock_bh(&routes->lock); - return err; + mutex_lock(&routes->lock); + if (dev == routes->table[daddr]) + rcu_assign_pointer(routes->table[daddr], NULL); + else + dev = NULL; + mutex_unlock(&routes->lock); + + if (!dev) + return -ENOENT; + synchronize_rcu(); + dev_put(dev); + return 0; } struct net_device *phonet_route_get(struct net *net, u8 daddr) @@ -397,9 +405,9 @@ struct net_device *phonet_route_get(struct net *net, u8 daddr) ASSERT_RTNL(); /* no need to hold the device */ daddr >>= 2; - spin_lock_bh(&routes->lock); - dev = routes->table[daddr]; - spin_unlock_bh(&routes->lock); + rcu_read_lock(); + dev = rcu_dereference(routes->table[daddr]); + rcu_read_unlock(); return dev; } @@ -409,11 +417,12 @@ struct net_device *phonet_route_output(struct net *net, u8 daddr) struct phonet_routes *routes = &pnn->routes; struct net_device *dev; - spin_lock_bh(&routes->lock); - dev = routes->table[daddr >> 2]; + daddr >>= 2; + rcu_read_lock(); + dev = rcu_dereference(routes->table[daddr]); if (dev) dev_hold(dev); - spin_unlock_bh(&routes->lock); + rcu_read_unlock(); if (!dev) dev = phonet_device_get(net); /* Default route */