diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bcast.c | 4 | ||||
-rw-r--r-- | net/tipc/diag.c | 2 | ||||
-rw-r--r-- | net/tipc/name_table.c | 10 | ||||
-rw-r--r-- | net/tipc/name_table.h | 9 | ||||
-rw-r--r-- | net/tipc/netlink.c | 2 | ||||
-rw-r--r-- | net/tipc/socket.c | 78 | ||||
-rw-r--r-- | net/tipc/socket.h | 2 | ||||
-rw-r--r-- | net/tipc/topsrv.c | 4 |
8 files changed, 68 insertions, 43 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 9ee6cfea56dd..d8026543bf4c 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -51,12 +51,12 @@ const char tipc_bclink_name[] = "broadcast-link"; | |||
51 | * struct tipc_bc_base - base structure for keeping broadcast send state | 51 | * struct tipc_bc_base - base structure for keeping broadcast send state |
52 | * @link: broadcast send link structure | 52 | * @link: broadcast send link structure |
53 | * @inputq: data input queue; will only carry SOCK_WAKEUP messages | 53 | * @inputq: data input queue; will only carry SOCK_WAKEUP messages |
54 | * @dest: array keeping number of reachable destinations per bearer | 54 | * @dests: array keeping number of reachable destinations per bearer |
55 | * @primary_bearer: a bearer having links to all broadcast destinations, if any | 55 | * @primary_bearer: a bearer having links to all broadcast destinations, if any |
56 | * @bcast_support: indicates if primary bearer, if any, supports broadcast | 56 | * @bcast_support: indicates if primary bearer, if any, supports broadcast |
57 | * @rcast_support: indicates if all peer nodes support replicast | 57 | * @rcast_support: indicates if all peer nodes support replicast |
58 | * @rc_ratio: dest count as percentage of cluster size where send method changes | 58 | * @rc_ratio: dest count as percentage of cluster size where send method changes |
59 | * @bc_threshold: calculated drom rc_ratio; if dests > threshold use broadcast | 59 | * @bc_threshold: calculated from rc_ratio; if dests > threshold use broadcast |
60 | */ | 60 | */ |
61 | struct tipc_bc_base { | 61 | struct tipc_bc_base { |
62 | struct tipc_link *link; | 62 | struct tipc_link *link; |
diff --git a/net/tipc/diag.c b/net/tipc/diag.c index aaabb0b776dd..73137f4aeb68 100644 --- a/net/tipc/diag.c +++ b/net/tipc/diag.c | |||
@@ -84,7 +84,9 @@ static int tipc_sock_diag_handler_dump(struct sk_buff *skb, | |||
84 | 84 | ||
85 | if (h->nlmsg_flags & NLM_F_DUMP) { | 85 | if (h->nlmsg_flags & NLM_F_DUMP) { |
86 | struct netlink_dump_control c = { | 86 | struct netlink_dump_control c = { |
87 | .start = tipc_dump_start, | ||
87 | .dump = tipc_diag_dump, | 88 | .dump = tipc_diag_dump, |
89 | .done = tipc_dump_done, | ||
88 | }; | 90 | }; |
89 | netlink_dump_start(net->diag_nlsk, skb, h, &c); | 91 | netlink_dump_start(net->diag_nlsk, skb, h, &c); |
90 | return 0; | 92 | return 0; |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 88f027b502f6..66d5b2c5987a 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -980,20 +980,17 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
980 | 980 | ||
981 | struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port) | 981 | struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port) |
982 | { | 982 | { |
983 | u64 value = (u64)node << 32 | port; | ||
984 | struct tipc_dest *dst; | 983 | struct tipc_dest *dst; |
985 | 984 | ||
986 | list_for_each_entry(dst, l, list) { | 985 | list_for_each_entry(dst, l, list) { |
987 | if (dst->value != value) | 986 | if (dst->node == node && dst->port == port) |
988 | continue; | 987 | return dst; |
989 | return dst; | ||
990 | } | 988 | } |
991 | return NULL; | 989 | return NULL; |
992 | } | 990 | } |
993 | 991 | ||
994 | bool tipc_dest_push(struct list_head *l, u32 node, u32 port) | 992 | bool tipc_dest_push(struct list_head *l, u32 node, u32 port) |
995 | { | 993 | { |
996 | u64 value = (u64)node << 32 | port; | ||
997 | struct tipc_dest *dst; | 994 | struct tipc_dest *dst; |
998 | 995 | ||
999 | if (tipc_dest_find(l, node, port)) | 996 | if (tipc_dest_find(l, node, port)) |
@@ -1002,7 +999,8 @@ bool tipc_dest_push(struct list_head *l, u32 node, u32 port) | |||
1002 | dst = kmalloc(sizeof(*dst), GFP_ATOMIC); | 999 | dst = kmalloc(sizeof(*dst), GFP_ATOMIC); |
1003 | if (unlikely(!dst)) | 1000 | if (unlikely(!dst)) |
1004 | return false; | 1001 | return false; |
1005 | dst->value = value; | 1002 | dst->node = node; |
1003 | dst->port = port; | ||
1006 | list_add(&dst->list, l); | 1004 | list_add(&dst->list, l); |
1007 | return true; | 1005 | return true; |
1008 | } | 1006 | } |
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 0febba41da86..892bd750b85f 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h | |||
@@ -133,13 +133,8 @@ void tipc_nametbl_stop(struct net *net); | |||
133 | 133 | ||
134 | struct tipc_dest { | 134 | struct tipc_dest { |
135 | struct list_head list; | 135 | struct list_head list; |
136 | union { | 136 | u32 port; |
137 | struct { | 137 | u32 node; |
138 | u32 port; | ||
139 | u32 node; | ||
140 | }; | ||
141 | u64 value; | ||
142 | }; | ||
143 | }; | 138 | }; |
144 | 139 | ||
145 | struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port); | 140 | struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port); |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 6ff2254088f6..99ee419210ba 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
@@ -167,7 +167,9 @@ static const struct genl_ops tipc_genl_v2_ops[] = { | |||
167 | }, | 167 | }, |
168 | { | 168 | { |
169 | .cmd = TIPC_NL_SOCK_GET, | 169 | .cmd = TIPC_NL_SOCK_GET, |
170 | .start = tipc_dump_start, | ||
170 | .dumpit = tipc_nl_sk_dump, | 171 | .dumpit = tipc_nl_sk_dump, |
172 | .done = tipc_dump_done, | ||
171 | .policy = tipc_nl_policy, | 173 | .policy = tipc_nl_policy, |
172 | }, | 174 | }, |
173 | { | 175 | { |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index c1e93c9515bc..ab7a2a7178f7 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -2672,6 +2672,8 @@ void tipc_sk_reinit(struct net *net) | |||
2672 | 2672 | ||
2673 | rhashtable_walk_stop(&iter); | 2673 | rhashtable_walk_stop(&iter); |
2674 | } while (tsk == ERR_PTR(-EAGAIN)); | 2674 | } while (tsk == ERR_PTR(-EAGAIN)); |
2675 | |||
2676 | rhashtable_walk_exit(&iter); | ||
2675 | } | 2677 | } |
2676 | 2678 | ||
2677 | static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid) | 2679 | static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid) |
@@ -3227,45 +3229,69 @@ int tipc_nl_sk_walk(struct sk_buff *skb, struct netlink_callback *cb, | |||
3227 | struct netlink_callback *cb, | 3229 | struct netlink_callback *cb, |
3228 | struct tipc_sock *tsk)) | 3230 | struct tipc_sock *tsk)) |
3229 | { | 3231 | { |
3230 | struct net *net = sock_net(skb->sk); | 3232 | struct rhashtable_iter *iter = (void *)cb->args[0]; |
3231 | struct tipc_net *tn = tipc_net(net); | ||
3232 | const struct bucket_table *tbl; | ||
3233 | u32 prev_portid = cb->args[1]; | ||
3234 | u32 tbl_id = cb->args[0]; | ||
3235 | struct rhash_head *pos; | ||
3236 | struct tipc_sock *tsk; | 3233 | struct tipc_sock *tsk; |
3237 | int err; | 3234 | int err; |
3238 | 3235 | ||
3239 | rcu_read_lock(); | 3236 | rhashtable_walk_start(iter); |
3240 | tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); | 3237 | while ((tsk = rhashtable_walk_next(iter)) != NULL) { |
3241 | for (; tbl_id < tbl->size; tbl_id++) { | 3238 | if (IS_ERR(tsk)) { |
3242 | rht_for_each_entry_rcu(tsk, pos, tbl, tbl_id, node) { | 3239 | err = PTR_ERR(tsk); |
3243 | spin_lock_bh(&tsk->sk.sk_lock.slock); | 3240 | if (err == -EAGAIN) { |
3244 | if (prev_portid && prev_portid != tsk->portid) { | 3241 | err = 0; |
3245 | spin_unlock_bh(&tsk->sk.sk_lock.slock); | ||
3246 | continue; | 3242 | continue; |
3247 | } | 3243 | } |
3244 | break; | ||
3245 | } | ||
3248 | 3246 | ||
3249 | err = skb_handler(skb, cb, tsk); | 3247 | sock_hold(&tsk->sk); |
3250 | if (err) { | 3248 | rhashtable_walk_stop(iter); |
3251 | prev_portid = tsk->portid; | 3249 | lock_sock(&tsk->sk); |
3252 | spin_unlock_bh(&tsk->sk.sk_lock.slock); | 3250 | err = skb_handler(skb, cb, tsk); |
3253 | goto out; | 3251 | if (err) { |
3254 | } | 3252 | release_sock(&tsk->sk); |
3255 | 3253 | sock_put(&tsk->sk); | |
3256 | prev_portid = 0; | 3254 | goto out; |
3257 | spin_unlock_bh(&tsk->sk.sk_lock.slock); | ||
3258 | } | 3255 | } |
3256 | release_sock(&tsk->sk); | ||
3257 | rhashtable_walk_start(iter); | ||
3258 | sock_put(&tsk->sk); | ||
3259 | } | 3259 | } |
3260 | rhashtable_walk_stop(iter); | ||
3260 | out: | 3261 | out: |
3261 | rcu_read_unlock(); | ||
3262 | cb->args[0] = tbl_id; | ||
3263 | cb->args[1] = prev_portid; | ||
3264 | |||
3265 | return skb->len; | 3262 | return skb->len; |
3266 | } | 3263 | } |
3267 | EXPORT_SYMBOL(tipc_nl_sk_walk); | 3264 | EXPORT_SYMBOL(tipc_nl_sk_walk); |
3268 | 3265 | ||
3266 | int tipc_dump_start(struct netlink_callback *cb) | ||
3267 | { | ||
3268 | struct rhashtable_iter *iter = (void *)cb->args[0]; | ||
3269 | struct net *net = sock_net(cb->skb->sk); | ||
3270 | struct tipc_net *tn = tipc_net(net); | ||
3271 | |||
3272 | if (!iter) { | ||
3273 | iter = kmalloc(sizeof(*iter), GFP_KERNEL); | ||
3274 | if (!iter) | ||
3275 | return -ENOMEM; | ||
3276 | |||
3277 | cb->args[0] = (long)iter; | ||
3278 | } | ||
3279 | |||
3280 | rhashtable_walk_enter(&tn->sk_rht, iter); | ||
3281 | return 0; | ||
3282 | } | ||
3283 | EXPORT_SYMBOL(tipc_dump_start); | ||
3284 | |||
3285 | int tipc_dump_done(struct netlink_callback *cb) | ||
3286 | { | ||
3287 | struct rhashtable_iter *hti = (void *)cb->args[0]; | ||
3288 | |||
3289 | rhashtable_walk_exit(hti); | ||
3290 | kfree(hti); | ||
3291 | return 0; | ||
3292 | } | ||
3293 | EXPORT_SYMBOL(tipc_dump_done); | ||
3294 | |||
3269 | int tipc_sk_fill_sock_diag(struct sk_buff *skb, struct netlink_callback *cb, | 3295 | int tipc_sk_fill_sock_diag(struct sk_buff *skb, struct netlink_callback *cb, |
3270 | struct tipc_sock *tsk, u32 sk_filter_state, | 3296 | struct tipc_sock *tsk, u32 sk_filter_state, |
3271 | u64 (*tipc_diag_gen_cookie)(struct sock *sk)) | 3297 | u64 (*tipc_diag_gen_cookie)(struct sock *sk)) |
diff --git a/net/tipc/socket.h b/net/tipc/socket.h index aff9b2ae5a1f..d43032e26532 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h | |||
@@ -68,4 +68,6 @@ int tipc_nl_sk_walk(struct sk_buff *skb, struct netlink_callback *cb, | |||
68 | int (*skb_handler)(struct sk_buff *skb, | 68 | int (*skb_handler)(struct sk_buff *skb, |
69 | struct netlink_callback *cb, | 69 | struct netlink_callback *cb, |
70 | struct tipc_sock *tsk)); | 70 | struct tipc_sock *tsk)); |
71 | int tipc_dump_start(struct netlink_callback *cb); | ||
72 | int tipc_dump_done(struct netlink_callback *cb); | ||
71 | #endif | 73 | #endif |
diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index c782b352d928..d8956f7daac4 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c | |||
@@ -307,8 +307,8 @@ static void tipc_conn_send_work(struct work_struct *work) | |||
307 | conn_put(con); | 307 | conn_put(con); |
308 | } | 308 | } |
309 | 309 | ||
310 | /* tipc_conn_queue_evt() - interrupt level call from a subscription instance | 310 | /* tipc_topsrv_queue_evt() - interrupt level call from a subscription instance |
311 | * The queued work is launched into tipc_send_work()->tipc_send_to_sock() | 311 | * The queued work is launched into tipc_conn_send_work()->tipc_conn_send_to_sock() |
312 | */ | 312 | */ |
313 | void tipc_topsrv_queue_evt(struct net *net, int conid, | 313 | void tipc_topsrv_queue_evt(struct net *net, int conid, |
314 | u32 event, struct tipc_event *evt) | 314 | u32 event, struct tipc_event *evt) |