o ipx: convert ipx_interface handling to use list_head

parent 277110dc
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <net/datalink.h> #include <net/datalink.h>
#include <linux/ipx.h> #include <linux/ipx.h>
#include <linux/list.h>
struct ipx_address { struct ipx_address {
__u32 net; __u32 net;
...@@ -66,7 +67,7 @@ struct ipx_interface { ...@@ -66,7 +67,7 @@ struct ipx_interface {
unsigned char if_internal; unsigned char if_internal;
unsigned char if_primary; unsigned char if_primary;
struct ipx_interface *if_next; struct list_head node; /* node in ipx_interfaces list */
}; };
struct ipx_route { struct ipx_route {
...@@ -113,7 +114,8 @@ struct ipx_opt { ...@@ -113,7 +114,8 @@ struct ipx_opt {
extern struct ipx_route *ipx_routes; extern struct ipx_route *ipx_routes;
extern rwlock_t ipx_routes_lock; extern rwlock_t ipx_routes_lock;
extern struct ipx_interface *ipx_interfaces; extern struct list_head ipx_interfaces;
extern struct ipx_interface *ipx_interfaces_head(void);
extern spinlock_t ipx_interfaces_lock; extern spinlock_t ipx_interfaces_lock;
extern struct ipx_interface *ipx_primary_net; extern struct ipx_interface *ipx_primary_net;
......
...@@ -84,7 +84,7 @@ static struct proto_ops ipx_dgram_ops; ...@@ -84,7 +84,7 @@ static struct proto_ops ipx_dgram_ops;
struct ipx_route *ipx_routes; struct ipx_route *ipx_routes;
rwlock_t ipx_routes_lock = RW_LOCK_UNLOCKED; rwlock_t ipx_routes_lock = RW_LOCK_UNLOCKED;
struct ipx_interface *ipx_interfaces; LIST_HEAD(ipx_interfaces);
spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED; spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED;
struct ipx_interface *ipx_primary_net; struct ipx_interface *ipx_primary_net;
...@@ -95,11 +95,21 @@ static struct ipx_interface *ipx_internal_net; ...@@ -95,11 +95,21 @@ static struct ipx_interface *ipx_internal_net;
atomic_t ipx_sock_nr; atomic_t ipx_sock_nr;
#endif #endif
struct ipx_interface *ipx_interfaces_head(void)
{
struct ipx_interface *rc = NULL;
if (!list_empty(&ipx_interfaces))
rc = list_entry(ipx_interfaces.next,
struct ipx_interface, node);
return rc;
}
static void ipxcfg_set_auto_select(char val) static void ipxcfg_set_auto_select(char val)
{ {
ipxcfg_auto_select_primary = val; ipxcfg_auto_select_primary = val;
if (val && !ipx_primary_net) if (val && !ipx_primary_net)
ipx_primary_net = ipx_interfaces; ipx_primary_net = ipx_interfaces_head();
} }
static int ipxcfg_get_config_data(struct ipx_config_data *arg) static int ipxcfg_get_config_data(struct ipx_config_data *arg)
...@@ -197,17 +207,21 @@ static struct ipx_route *ipxrtr_lookup(__u32 net); ...@@ -197,17 +207,21 @@ static struct ipx_route *ipxrtr_lookup(__u32 net);
static void ipxitf_clear_primary_net(void) static void ipxitf_clear_primary_net(void)
{ {
ipx_primary_net = ipxcfg_auto_select_primary ? ipx_interfaces : NULL; ipx_primary_net = NULL;
if (ipxcfg_auto_select_primary)
ipx_primary_net = ipx_interfaces_head();
} }
static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev, static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
unsigned short datalink) unsigned short datalink)
{ {
struct ipx_interface *i = ipx_interfaces; struct ipx_interface *i;
while (i && (i->if_dev != dev || i->if_dlink_type != datalink))
i = i->if_next;
list_for_each_entry(i, &ipx_interfaces, node)
if (i->if_dev == dev && i->if_dlink_type == datalink)
goto out;
i = NULL;
out:
return i; return i;
} }
...@@ -229,16 +243,20 @@ static struct ipx_interface *ipxitf_find_using_net(__u32 net) ...@@ -229,16 +243,20 @@ static struct ipx_interface *ipxitf_find_using_net(__u32 net)
struct ipx_interface *i; struct ipx_interface *i;
spin_lock_bh(&ipx_interfaces_lock); spin_lock_bh(&ipx_interfaces_lock);
if (net) if (net) {
for (i = ipx_interfaces; i && i->if_netnum != net; list_for_each_entry(i, &ipx_interfaces, node)
i = i->if_next) if (i->if_netnum == net)
; goto hold;
else i = NULL;
i = ipx_primary_net; goto unlock;
}
i = ipx_primary_net;
if (i) if (i)
hold:
ipxitf_hold(i); ipxitf_hold(i);
unlock:
spin_unlock_bh(&ipx_interfaces_lock); spin_unlock_bh(&ipx_interfaces_lock);
return i; return i;
} }
...@@ -342,15 +360,7 @@ static void __ipxitf_down(struct ipx_interface *intrfc) ...@@ -342,15 +360,7 @@ static void __ipxitf_down(struct ipx_interface *intrfc)
spin_unlock_bh(&intrfc->if_sklist_lock); spin_unlock_bh(&intrfc->if_sklist_lock);
/* remove this interface from list */ /* remove this interface from list */
if (intrfc == ipx_interfaces) list_del(&intrfc->node);
ipx_interfaces = intrfc->if_next;
else {
struct ipx_interface *i = ipx_interfaces;
while (i && i->if_next != intrfc)
i = i->if_next;
if (i && i->if_next == intrfc)
i->if_next = intrfc->if_next;
}
/* remove this interface from *special* networks */ /* remove this interface from *special* networks */
if (intrfc == ipx_primary_net) if (intrfc == ipx_primary_net)
...@@ -380,16 +390,13 @@ static int ipxitf_device_event(struct notifier_block *notifier, ...@@ -380,16 +390,13 @@ static int ipxitf_device_event(struct notifier_block *notifier,
goto out; goto out;
spin_lock_bh(&ipx_interfaces_lock); spin_lock_bh(&ipx_interfaces_lock);
for (i = ipx_interfaces; i;) { list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
tmp = i->if_next;
if (i->if_dev == dev) { if (i->if_dev == dev) {
if (event == NETDEV_UP) if (event == NETDEV_UP)
ipxitf_hold(i); ipxitf_hold(i);
else else
__ipxitf_put(i); __ipxitf_put(i);
} }
i = tmp;
}
spin_unlock_bh(&ipx_interfaces_lock); spin_unlock_bh(&ipx_interfaces_lock);
out: out:
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -872,7 +879,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) ...@@ -872,7 +879,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum; IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum;
/* xmit on all other interfaces... */ /* xmit on all other interfaces... */
spin_lock_bh(&ipx_interfaces_lock); spin_lock_bh(&ipx_interfaces_lock);
for (ifcs = ipx_interfaces; ifcs; ifcs = ifcs->if_next) { list_for_each_entry(ifcs, &ipx_interfaces, node) {
/* Except unconfigured interfaces */ /* Except unconfigured interfaces */
if (!ifcs->if_netnum) if (!ifcs->if_netnum)
continue; continue;
...@@ -902,16 +909,8 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) ...@@ -902,16 +909,8 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
static void ipxitf_insert(struct ipx_interface *intrfc) static void ipxitf_insert(struct ipx_interface *intrfc)
{ {
intrfc->if_next = NULL;
spin_lock_bh(&ipx_interfaces_lock); spin_lock_bh(&ipx_interfaces_lock);
if (!ipx_interfaces) list_add_tail(&intrfc->node, &ipx_interfaces);
ipx_interfaces = intrfc;
else {
struct ipx_interface *i = ipx_interfaces;
while (i->if_next)
i = i->if_next;
i->if_next = intrfc;
}
spin_unlock_bh(&ipx_interfaces_lock); spin_unlock_bh(&ipx_interfaces_lock);
if (ipxcfg_auto_select_primary && !ipx_primary_net) if (ipxcfg_auto_select_primary && !ipx_primary_net)
......
...@@ -17,12 +17,23 @@ static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos) ...@@ -17,12 +17,23 @@ static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos)
{ {
struct ipx_interface *i; struct ipx_interface *i;
for (i = ipx_interfaces; pos && i; i = i->if_next) list_for_each_entry(i, &ipx_interfaces, node)
--pos; if (!pos--)
goto out;
i = NULL;
out:
return i; return i;
} }
static struct ipx_interface *ipx_interfaces_next(struct ipx_interface *i)
{
struct ipx_interface *rc = NULL;
if (i->node.next != &ipx_interfaces)
rc = list_entry(i->node.next, struct ipx_interface, node);
return rc;
}
static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos)
{ {
loff_t l = *pos; loff_t l = *pos;
...@@ -36,15 +47,10 @@ static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -36,15 +47,10 @@ static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos)
struct ipx_interface *i; struct ipx_interface *i;
++*pos; ++*pos;
if (v == (void *)1) { if (v == (void *)1)
i = NULL; i = ipx_interfaces_head();
if (ipx_interfaces) else
i = ipx_interfaces; i = ipx_interfaces_next(v);
goto out;
}
i = v;
i = i->if_next;
out:
return i; return i;
} }
...@@ -149,7 +155,9 @@ static __inline__ struct sock *ipx_get_socket_idx(loff_t pos) ...@@ -149,7 +155,9 @@ static __inline__ struct sock *ipx_get_socket_idx(loff_t pos)
struct sock *s = NULL; struct sock *s = NULL;
struct ipx_interface *i; struct ipx_interface *i;
for (i = ipx_interfaces; pos && i; i = i->if_next) { list_for_each_entry(i, &ipx_interfaces, node) {
if (!pos)
break;
spin_lock_bh(&i->if_sklist_lock); spin_lock_bh(&i->if_sklist_lock);
for (s = i->if_sklist; pos && s; s = s->next) for (s = i->if_sklist; pos && s; s = s->next)
--pos; --pos;
...@@ -181,11 +189,12 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -181,11 +189,12 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
++*pos; ++*pos;
if (v == (void *)1) { if (v == (void *)1) {
sk = NULL; sk = NULL;
if (!ipx_interfaces) i = ipx_interfaces_head();
if (!i)
goto out; goto out;
sk = ipx_interfaces->if_sklist; sk = i->if_sklist;
if (sk) if (sk)
spin_lock_bh(&ipx_interfaces->if_sklist_lock); spin_lock_bh(&i->if_sklist_lock);
goto out; goto out;
} }
sk = v; sk = v;
...@@ -198,9 +207,9 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -198,9 +207,9 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
spin_unlock_bh(&i->if_sklist_lock); spin_unlock_bh(&i->if_sklist_lock);
sk = NULL; sk = NULL;
for (;;) { for (;;) {
if (!i->if_next) i = ipx_interfaces_next(i);
if (!i)
break; break;
i = i->if_next;
spin_lock_bh(&i->if_sklist_lock); spin_lock_bh(&i->if_sklist_lock);
if (i->if_sklist) { if (i->if_sklist) {
sk = i->if_sklist; sk = i->if_sklist;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment