diff options
Diffstat (limited to 'net/llc/llc_proc.c')
-rw-r--r-- | net/llc/llc_proc.c | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index be47ac427f6b..7af1ff2d1f19 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c | |||
@@ -32,21 +32,23 @@ static void llc_ui_format_mac(struct seq_file *seq, u8 *addr) | |||
32 | 32 | ||
33 | static struct sock *llc_get_sk_idx(loff_t pos) | 33 | static struct sock *llc_get_sk_idx(loff_t pos) |
34 | { | 34 | { |
35 | struct list_head *sap_entry; | ||
36 | struct llc_sap *sap; | 35 | struct llc_sap *sap; |
37 | struct hlist_node *node; | ||
38 | struct sock *sk = NULL; | 36 | struct sock *sk = NULL; |
39 | 37 | int i; | |
40 | list_for_each(sap_entry, &llc_sap_list) { | 38 | |
41 | sap = list_entry(sap_entry, struct llc_sap, node); | 39 | list_for_each_entry_rcu(sap, &llc_sap_list, node) { |
42 | 40 | spin_lock_bh(&sap->sk_lock); | |
43 | read_lock_bh(&sap->sk_list.lock); | 41 | for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++) { |
44 | sk_for_each(sk, node, &sap->sk_list.list) { | 42 | struct hlist_nulls_head *head = &sap->sk_laddr_hash[i]; |
45 | if (!pos) | 43 | struct hlist_nulls_node *node; |
46 | goto found; | 44 | |
47 | --pos; | 45 | sk_nulls_for_each(sk, node, head) { |
46 | if (!pos) | ||
47 | goto found; /* keep the lock */ | ||
48 | --pos; | ||
49 | } | ||
48 | } | 50 | } |
49 | read_unlock_bh(&sap->sk_list.lock); | 51 | spin_unlock_bh(&sap->sk_lock); |
50 | } | 52 | } |
51 | sk = NULL; | 53 | sk = NULL; |
52 | found: | 54 | found: |
@@ -57,10 +59,23 @@ static void *llc_seq_start(struct seq_file *seq, loff_t *pos) | |||
57 | { | 59 | { |
58 | loff_t l = *pos; | 60 | loff_t l = *pos; |
59 | 61 | ||
60 | read_lock_bh(&llc_sap_list_lock); | 62 | rcu_read_lock_bh(); |
61 | return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN; | 63 | return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN; |
62 | } | 64 | } |
63 | 65 | ||
66 | static struct sock *laddr_hash_next(struct llc_sap *sap, int bucket) | ||
67 | { | ||
68 | struct hlist_nulls_node *node; | ||
69 | struct sock *sk = NULL; | ||
70 | |||
71 | while (++bucket < LLC_SK_LADDR_HASH_ENTRIES) | ||
72 | sk_nulls_for_each(sk, node, &sap->sk_laddr_hash[bucket]) | ||
73 | goto out; | ||
74 | |||
75 | out: | ||
76 | return sk; | ||
77 | } | ||
78 | |||
64 | static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 79 | static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
65 | { | 80 | { |
66 | struct sock* sk, *next; | 81 | struct sock* sk, *next; |
@@ -73,25 +88,23 @@ static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
73 | goto out; | 88 | goto out; |
74 | } | 89 | } |
75 | sk = v; | 90 | sk = v; |
76 | next = sk_next(sk); | 91 | next = sk_nulls_next(sk); |
77 | if (next) { | 92 | if (next) { |
78 | sk = next; | 93 | sk = next; |
79 | goto out; | 94 | goto out; |
80 | } | 95 | } |
81 | llc = llc_sk(sk); | 96 | llc = llc_sk(sk); |
82 | sap = llc->sap; | 97 | sap = llc->sap; |
83 | read_unlock_bh(&sap->sk_list.lock); | 98 | sk = laddr_hash_next(sap, llc_sk_laddr_hashfn(sap, &llc->laddr)); |
84 | sk = NULL; | 99 | if (sk) |
85 | for (;;) { | 100 | goto out; |
86 | if (sap->node.next == &llc_sap_list) | 101 | spin_unlock_bh(&sap->sk_lock); |
87 | break; | 102 | list_for_each_entry_continue_rcu(sap, &llc_sap_list, node) { |
88 | sap = list_entry(sap->node.next, struct llc_sap, node); | 103 | spin_lock_bh(&sap->sk_lock); |
89 | read_lock_bh(&sap->sk_list.lock); | 104 | sk = laddr_hash_next(sap, -1); |
90 | if (!hlist_empty(&sap->sk_list.list)) { | 105 | if (sk) |
91 | sk = sk_head(&sap->sk_list.list); | 106 | break; /* keep the lock */ |
92 | break; | 107 | spin_unlock_bh(&sap->sk_lock); |
93 | } | ||
94 | read_unlock_bh(&sap->sk_list.lock); | ||
95 | } | 108 | } |
96 | out: | 109 | out: |
97 | return sk; | 110 | return sk; |
@@ -104,9 +117,9 @@ static void llc_seq_stop(struct seq_file *seq, void *v) | |||
104 | struct llc_sock *llc = llc_sk(sk); | 117 | struct llc_sock *llc = llc_sk(sk); |
105 | struct llc_sap *sap = llc->sap; | 118 | struct llc_sap *sap = llc->sap; |
106 | 119 | ||
107 | read_unlock_bh(&sap->sk_list.lock); | 120 | spin_unlock_bh(&sap->sk_lock); |
108 | } | 121 | } |
109 | read_unlock_bh(&llc_sap_list_lock); | 122 | rcu_read_unlock_bh(); |
110 | } | 123 | } |
111 | 124 | ||
112 | static int llc_seq_socket_show(struct seq_file *seq, void *v) | 125 | static int llc_seq_socket_show(struct seq_file *seq, void *v) |