diff options
Diffstat (limited to 'net/tipc/name_distr.c')
| -rw-r--r-- | net/tipc/name_distr.c | 181 |
1 files changed, 94 insertions, 87 deletions
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 376d2bb51d8d..ba6083dca95b 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
| @@ -38,39 +38,6 @@ | |||
| 38 | #include "link.h" | 38 | #include "link.h" |
| 39 | #include "name_distr.h" | 39 | #include "name_distr.h" |
| 40 | 40 | ||
| 41 | /** | ||
| 42 | * struct publ_list - list of publications made by this node | ||
| 43 | * @list: circular list of publications | ||
| 44 | * @list_size: number of entries in list | ||
| 45 | */ | ||
| 46 | struct publ_list { | ||
| 47 | struct list_head list; | ||
| 48 | u32 size; | ||
| 49 | }; | ||
| 50 | |||
| 51 | static struct publ_list publ_zone = { | ||
| 52 | .list = LIST_HEAD_INIT(publ_zone.list), | ||
| 53 | .size = 0, | ||
| 54 | }; | ||
| 55 | |||
| 56 | static struct publ_list publ_cluster = { | ||
| 57 | .list = LIST_HEAD_INIT(publ_cluster.list), | ||
| 58 | .size = 0, | ||
| 59 | }; | ||
| 60 | |||
| 61 | static struct publ_list publ_node = { | ||
| 62 | .list = LIST_HEAD_INIT(publ_node.list), | ||
| 63 | .size = 0, | ||
| 64 | }; | ||
| 65 | |||
| 66 | static struct publ_list *publ_lists[] = { | ||
| 67 | NULL, | ||
| 68 | &publ_zone, /* publ_lists[TIPC_ZONE_SCOPE] */ | ||
| 69 | &publ_cluster, /* publ_lists[TIPC_CLUSTER_SCOPE] */ | ||
| 70 | &publ_node /* publ_lists[TIPC_NODE_SCOPE] */ | ||
| 71 | }; | ||
| 72 | |||
| 73 | |||
| 74 | int sysctl_tipc_named_timeout __read_mostly = 2000; | 41 | int sysctl_tipc_named_timeout __read_mostly = 2000; |
| 75 | 42 | ||
| 76 | /** | 43 | /** |
| @@ -114,9 +81,9 @@ static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) | |||
| 114 | return buf; | 81 | return buf; |
| 115 | } | 82 | } |
| 116 | 83 | ||
| 117 | void named_cluster_distribute(struct sk_buff *buf) | 84 | void named_cluster_distribute(struct sk_buff *skb) |
| 118 | { | 85 | { |
| 119 | struct sk_buff *obuf; | 86 | struct sk_buff *oskb; |
| 120 | struct tipc_node *node; | 87 | struct tipc_node *node; |
| 121 | u32 dnode; | 88 | u32 dnode; |
| 122 | 89 | ||
| @@ -127,15 +94,15 @@ void named_cluster_distribute(struct sk_buff *buf) | |||
| 127 | continue; | 94 | continue; |
| 128 | if (!tipc_node_active_links(node)) | 95 | if (!tipc_node_active_links(node)) |
| 129 | continue; | 96 | continue; |
| 130 | obuf = skb_copy(buf, GFP_ATOMIC); | 97 | oskb = skb_copy(skb, GFP_ATOMIC); |
| 131 | if (!obuf) | 98 | if (!oskb) |
| 132 | break; | 99 | break; |
| 133 | msg_set_destnode(buf_msg(obuf), dnode); | 100 | msg_set_destnode(buf_msg(oskb), dnode); |
| 134 | tipc_link_xmit(obuf, dnode, dnode); | 101 | tipc_link_xmit_skb(oskb, dnode, dnode); |
| 135 | } | 102 | } |
| 136 | rcu_read_unlock(); | 103 | rcu_read_unlock(); |
| 137 | 104 | ||
| 138 | kfree_skb(buf); | 105 | kfree_skb(skb); |
| 139 | } | 106 | } |
| 140 | 107 | ||
| 141 | /** | 108 | /** |
| @@ -146,8 +113,8 @@ struct sk_buff *tipc_named_publish(struct publication *publ) | |||
| 146 | struct sk_buff *buf; | 113 | struct sk_buff *buf; |
| 147 | struct distr_item *item; | 114 | struct distr_item *item; |
| 148 | 115 | ||
| 149 | list_add_tail(&publ->local_list, &publ_lists[publ->scope]->list); | 116 | list_add_tail_rcu(&publ->local_list, |
| 150 | publ_lists[publ->scope]->size++; | 117 | &tipc_nametbl->publ_list[publ->scope]); |
| 151 | 118 | ||
| 152 | if (publ->scope == TIPC_NODE_SCOPE) | 119 | if (publ->scope == TIPC_NODE_SCOPE) |
| 153 | return NULL; | 120 | return NULL; |
| @@ -172,7 +139,6 @@ struct sk_buff *tipc_named_withdraw(struct publication *publ) | |||
| 172 | struct distr_item *item; | 139 | struct distr_item *item; |
| 173 | 140 | ||
| 174 | list_del(&publ->local_list); | 141 | list_del(&publ->local_list); |
| 175 | publ_lists[publ->scope]->size--; | ||
| 176 | 142 | ||
| 177 | if (publ->scope == TIPC_NODE_SCOPE) | 143 | if (publ->scope == TIPC_NODE_SCOPE) |
| 178 | return NULL; | 144 | return NULL; |
| @@ -190,32 +156,28 @@ struct sk_buff *tipc_named_withdraw(struct publication *publ) | |||
| 190 | 156 | ||
| 191 | /** | 157 | /** |
| 192 | * named_distribute - prepare name info for bulk distribution to another node | 158 | * named_distribute - prepare name info for bulk distribution to another node |
| 193 | * @msg_list: list of messages (buffers) to be returned from this function | 159 | * @list: list of messages (buffers) to be returned from this function |
| 194 | * @dnode: node to be updated | 160 | * @dnode: node to be updated |
| 195 | * @pls: linked list of publication items to be packed into buffer chain | 161 | * @pls: linked list of publication items to be packed into buffer chain |
| 196 | */ | 162 | */ |
| 197 | static void named_distribute(struct list_head *msg_list, u32 dnode, | 163 | static void named_distribute(struct sk_buff_head *list, u32 dnode, |
| 198 | struct publ_list *pls) | 164 | struct list_head *pls) |
| 199 | { | 165 | { |
| 200 | struct publication *publ; | 166 | struct publication *publ; |
| 201 | struct sk_buff *buf = NULL; | 167 | struct sk_buff *skb = NULL; |
| 202 | struct distr_item *item = NULL; | 168 | struct distr_item *item = NULL; |
| 203 | uint dsz = pls->size * ITEM_SIZE; | ||
| 204 | uint msg_dsz = (tipc_node_get_mtu(dnode, 0) / ITEM_SIZE) * ITEM_SIZE; | 169 | uint msg_dsz = (tipc_node_get_mtu(dnode, 0) / ITEM_SIZE) * ITEM_SIZE; |
| 205 | uint rem = dsz; | 170 | uint msg_rem = msg_dsz; |
| 206 | uint msg_rem = 0; | ||
| 207 | 171 | ||
| 208 | list_for_each_entry(publ, &pls->list, local_list) { | 172 | list_for_each_entry(publ, pls, local_list) { |
| 209 | /* Prepare next buffer: */ | 173 | /* Prepare next buffer: */ |
| 210 | if (!buf) { | 174 | if (!skb) { |
| 211 | msg_rem = min_t(uint, rem, msg_dsz); | 175 | skb = named_prepare_buf(PUBLICATION, msg_rem, dnode); |
| 212 | rem -= msg_rem; | 176 | if (!skb) { |
| 213 | buf = named_prepare_buf(PUBLICATION, msg_rem, dnode); | ||
| 214 | if (!buf) { | ||
| 215 | pr_warn("Bulk publication failure\n"); | 177 | pr_warn("Bulk publication failure\n"); |
| 216 | return; | 178 | return; |
| 217 | } | 179 | } |
| 218 | item = (struct distr_item *)msg_data(buf_msg(buf)); | 180 | item = (struct distr_item *)msg_data(buf_msg(skb)); |
| 219 | } | 181 | } |
| 220 | 182 | ||
| 221 | /* Pack publication into message: */ | 183 | /* Pack publication into message: */ |
| @@ -225,10 +187,16 @@ static void named_distribute(struct list_head *msg_list, u32 dnode, | |||
| 225 | 187 | ||
| 226 | /* Append full buffer to list: */ | 188 | /* Append full buffer to list: */ |
| 227 | if (!msg_rem) { | 189 | if (!msg_rem) { |
| 228 | list_add_tail((struct list_head *)buf, msg_list); | 190 | __skb_queue_tail(list, skb); |
| 229 | buf = NULL; | 191 | skb = NULL; |
| 192 | msg_rem = msg_dsz; | ||
| 230 | } | 193 | } |
| 231 | } | 194 | } |
| 195 | if (skb) { | ||
| 196 | msg_set_size(buf_msg(skb), INT_H_SIZE + (msg_dsz - msg_rem)); | ||
| 197 | skb_trim(skb, INT_H_SIZE + (msg_dsz - msg_rem)); | ||
| 198 | __skb_queue_tail(list, skb); | ||
| 199 | } | ||
| 232 | } | 200 | } |
| 233 | 201 | ||
| 234 | /** | 202 | /** |
| @@ -236,36 +204,68 @@ static void named_distribute(struct list_head *msg_list, u32 dnode, | |||
| 236 | */ | 204 | */ |
| 237 | void tipc_named_node_up(u32 dnode) | 205 | void tipc_named_node_up(u32 dnode) |
| 238 | { | 206 | { |
| 239 | LIST_HEAD(msg_list); | 207 | struct sk_buff_head head; |
| 240 | struct sk_buff *buf_chain; | 208 | |
| 241 | 209 | __skb_queue_head_init(&head); | |
| 242 | read_lock_bh(&tipc_nametbl_lock); | 210 | |
| 243 | named_distribute(&msg_list, dnode, &publ_cluster); | 211 | rcu_read_lock(); |
| 244 | named_distribute(&msg_list, dnode, &publ_zone); | 212 | named_distribute(&head, dnode, |
| 245 | read_unlock_bh(&tipc_nametbl_lock); | 213 | &tipc_nametbl->publ_list[TIPC_CLUSTER_SCOPE]); |
| 246 | 214 | named_distribute(&head, dnode, | |
| 247 | /* Convert circular list to linear list and send: */ | 215 | &tipc_nametbl->publ_list[TIPC_ZONE_SCOPE]); |
| 248 | buf_chain = (struct sk_buff *)msg_list.next; | 216 | rcu_read_unlock(); |
| 249 | ((struct sk_buff *)msg_list.prev)->next = NULL; | 217 | |
| 250 | tipc_link_xmit(buf_chain, dnode, dnode); | 218 | tipc_link_xmit(&head, dnode, dnode); |
| 219 | } | ||
| 220 | |||
| 221 | static void tipc_publ_subscribe(struct publication *publ, u32 addr) | ||
| 222 | { | ||
| 223 | struct tipc_node *node; | ||
| 224 | |||
| 225 | if (in_own_node(addr)) | ||
| 226 | return; | ||
| 227 | |||
| 228 | node = tipc_node_find(addr); | ||
| 229 | if (!node) { | ||
| 230 | pr_warn("Node subscription rejected, unknown node 0x%x\n", | ||
| 231 | addr); | ||
| 232 | return; | ||
| 233 | } | ||
| 234 | |||
| 235 | tipc_node_lock(node); | ||
| 236 | list_add_tail(&publ->nodesub_list, &node->publ_list); | ||
| 237 | tipc_node_unlock(node); | ||
| 238 | } | ||
| 239 | |||
| 240 | static void tipc_publ_unsubscribe(struct publication *publ, u32 addr) | ||
| 241 | { | ||
| 242 | struct tipc_node *node; | ||
| 243 | |||
| 244 | node = tipc_node_find(addr); | ||
| 245 | if (!node) | ||
| 246 | return; | ||
| 247 | |||
| 248 | tipc_node_lock(node); | ||
| 249 | list_del_init(&publ->nodesub_list); | ||
| 250 | tipc_node_unlock(node); | ||
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | /** | 253 | /** |
| 254 | * named_purge_publ - remove publication associated with a failed node | 254 | * tipc_publ_purge - remove publication associated with a failed node |
| 255 | * | 255 | * |
| 256 | * Invoked for each publication issued by a newly failed node. | 256 | * Invoked for each publication issued by a newly failed node. |
| 257 | * Removes publication structure from name table & deletes it. | 257 | * Removes publication structure from name table & deletes it. |
| 258 | */ | 258 | */ |
| 259 | static void named_purge_publ(struct publication *publ) | 259 | static void tipc_publ_purge(struct publication *publ, u32 addr) |
| 260 | { | 260 | { |
| 261 | struct publication *p; | 261 | struct publication *p; |
| 262 | 262 | ||
| 263 | write_lock_bh(&tipc_nametbl_lock); | 263 | spin_lock_bh(&tipc_nametbl_lock); |
| 264 | p = tipc_nametbl_remove_publ(publ->type, publ->lower, | 264 | p = tipc_nametbl_remove_publ(publ->type, publ->lower, |
| 265 | publ->node, publ->ref, publ->key); | 265 | publ->node, publ->ref, publ->key); |
| 266 | if (p) | 266 | if (p) |
| 267 | tipc_nodesub_unsubscribe(&p->subscr); | 267 | tipc_publ_unsubscribe(p, addr); |
| 268 | write_unlock_bh(&tipc_nametbl_lock); | 268 | spin_unlock_bh(&tipc_nametbl_lock); |
| 269 | 269 | ||
| 270 | if (p != publ) { | 270 | if (p != publ) { |
| 271 | pr_err("Unable to remove publication from failed node\n" | 271 | pr_err("Unable to remove publication from failed node\n" |
| @@ -274,7 +274,15 @@ static void named_purge_publ(struct publication *publ) | |||
| 274 | publ->key); | 274 | publ->key); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | kfree(p); | 277 | kfree_rcu(p, rcu); |
| 278 | } | ||
| 279 | |||
| 280 | void tipc_publ_notify(struct list_head *nsub_list, u32 addr) | ||
| 281 | { | ||
| 282 | struct publication *publ, *tmp; | ||
| 283 | |||
| 284 | list_for_each_entry_safe(publ, tmp, nsub_list, nodesub_list) | ||
| 285 | tipc_publ_purge(publ, addr); | ||
| 278 | } | 286 | } |
| 279 | 287 | ||
| 280 | /** | 288 | /** |
| @@ -294,9 +302,7 @@ static bool tipc_update_nametbl(struct distr_item *i, u32 node, u32 dtype) | |||
| 294 | TIPC_CLUSTER_SCOPE, node, | 302 | TIPC_CLUSTER_SCOPE, node, |
| 295 | ntohl(i->ref), ntohl(i->key)); | 303 | ntohl(i->ref), ntohl(i->key)); |
| 296 | if (publ) { | 304 | if (publ) { |
| 297 | tipc_nodesub_subscribe(&publ->subscr, node, publ, | 305 | tipc_publ_subscribe(publ, node); |
| 298 | (net_ev_handler) | ||
| 299 | named_purge_publ); | ||
| 300 | return true; | 306 | return true; |
| 301 | } | 307 | } |
| 302 | } else if (dtype == WITHDRAWAL) { | 308 | } else if (dtype == WITHDRAWAL) { |
| @@ -304,8 +310,8 @@ static bool tipc_update_nametbl(struct distr_item *i, u32 node, u32 dtype) | |||
| 304 | node, ntohl(i->ref), | 310 | node, ntohl(i->ref), |
| 305 | ntohl(i->key)); | 311 | ntohl(i->key)); |
| 306 | if (publ) { | 312 | if (publ) { |
| 307 | tipc_nodesub_unsubscribe(&publ->subscr); | 313 | tipc_publ_unsubscribe(publ, node); |
| 308 | kfree(publ); | 314 | kfree_rcu(publ, rcu); |
| 309 | return true; | 315 | return true; |
| 310 | } | 316 | } |
| 311 | } else { | 317 | } else { |
| @@ -370,14 +376,14 @@ void tipc_named_rcv(struct sk_buff *buf) | |||
| 370 | u32 count = msg_data_sz(msg) / ITEM_SIZE; | 376 | u32 count = msg_data_sz(msg) / ITEM_SIZE; |
| 371 | u32 node = msg_orignode(msg); | 377 | u32 node = msg_orignode(msg); |
| 372 | 378 | ||
| 373 | write_lock_bh(&tipc_nametbl_lock); | 379 | spin_lock_bh(&tipc_nametbl_lock); |
| 374 | while (count--) { | 380 | while (count--) { |
| 375 | if (!tipc_update_nametbl(item, node, msg_type(msg))) | 381 | if (!tipc_update_nametbl(item, node, msg_type(msg))) |
| 376 | tipc_named_add_backlog(item, msg_type(msg), node); | 382 | tipc_named_add_backlog(item, msg_type(msg), node); |
| 377 | item++; | 383 | item++; |
| 378 | } | 384 | } |
| 379 | tipc_named_process_backlog(); | 385 | tipc_named_process_backlog(); |
| 380 | write_unlock_bh(&tipc_nametbl_lock); | 386 | spin_unlock_bh(&tipc_nametbl_lock); |
| 381 | kfree_skb(buf); | 387 | kfree_skb(buf); |
| 382 | } | 388 | } |
| 383 | 389 | ||
| @@ -393,11 +399,12 @@ void tipc_named_reinit(void) | |||
| 393 | struct publication *publ; | 399 | struct publication *publ; |
| 394 | int scope; | 400 | int scope; |
| 395 | 401 | ||
| 396 | write_lock_bh(&tipc_nametbl_lock); | 402 | spin_lock_bh(&tipc_nametbl_lock); |
| 397 | 403 | ||
| 398 | for (scope = TIPC_ZONE_SCOPE; scope <= TIPC_NODE_SCOPE; scope++) | 404 | for (scope = TIPC_ZONE_SCOPE; scope <= TIPC_NODE_SCOPE; scope++) |
| 399 | list_for_each_entry(publ, &publ_lists[scope]->list, local_list) | 405 | list_for_each_entry_rcu(publ, &tipc_nametbl->publ_list[scope], |
| 406 | local_list) | ||
| 400 | publ->node = tipc_own_addr; | 407 | publ->node = tipc_own_addr; |
| 401 | 408 | ||
| 402 | write_unlock_bh(&tipc_nametbl_lock); | 409 | spin_unlock_bh(&tipc_nametbl_lock); |
| 403 | } | 410 | } |
