diff options
Diffstat (limited to 'net/tipc/subscr.c')
| -rw-r--r-- | net/tipc/subscr.c | 131 |
1 files changed, 75 insertions, 56 deletions
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 0344206b984f..72c339e432aa 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
| @@ -50,33 +50,6 @@ struct tipc_subscriber { | |||
| 50 | struct list_head subscription_list; | 50 | struct list_head subscription_list; |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr, | ||
| 54 | void *usr_data, void *buf, size_t len); | ||
| 55 | static void *subscr_named_msg_event(int conid); | ||
| 56 | static void subscr_conn_shutdown_event(int conid, void *usr_data); | ||
| 57 | |||
| 58 | static atomic_t subscription_count = ATOMIC_INIT(0); | ||
| 59 | |||
| 60 | static struct sockaddr_tipc topsrv_addr __read_mostly = { | ||
| 61 | .family = AF_TIPC, | ||
| 62 | .addrtype = TIPC_ADDR_NAMESEQ, | ||
| 63 | .addr.nameseq.type = TIPC_TOP_SRV, | ||
| 64 | .addr.nameseq.lower = TIPC_TOP_SRV, | ||
| 65 | .addr.nameseq.upper = TIPC_TOP_SRV, | ||
| 66 | .scope = TIPC_NODE_SCOPE | ||
| 67 | }; | ||
| 68 | |||
| 69 | static struct tipc_server topsrv __read_mostly = { | ||
| 70 | .saddr = &topsrv_addr, | ||
| 71 | .imp = TIPC_CRITICAL_IMPORTANCE, | ||
| 72 | .type = SOCK_SEQPACKET, | ||
| 73 | .max_rcvbuf_size = sizeof(struct tipc_subscr), | ||
| 74 | .name = "topology_server", | ||
| 75 | .tipc_conn_recvmsg = subscr_conn_msg_event, | ||
| 76 | .tipc_conn_new = subscr_named_msg_event, | ||
| 77 | .tipc_conn_shutdown = subscr_conn_shutdown_event, | ||
| 78 | }; | ||
| 79 | |||
| 80 | /** | 53 | /** |
| 81 | * htohl - convert value to endianness used by destination | 54 | * htohl - convert value to endianness used by destination |
| 82 | * @in: value to convert | 55 | * @in: value to convert |
| @@ -93,6 +66,7 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, | |||
| 93 | u32 found_upper, u32 event, u32 port_ref, | 66 | u32 found_upper, u32 event, u32 port_ref, |
| 94 | u32 node) | 67 | u32 node) |
| 95 | { | 68 | { |
| 69 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); | ||
| 96 | struct tipc_subscriber *subscriber = sub->subscriber; | 70 | struct tipc_subscriber *subscriber = sub->subscriber; |
| 97 | struct kvec msg_sect; | 71 | struct kvec msg_sect; |
| 98 | 72 | ||
| @@ -103,8 +77,8 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, | |||
| 103 | sub->evt.found_upper = htohl(found_upper, sub->swap); | 77 | sub->evt.found_upper = htohl(found_upper, sub->swap); |
| 104 | sub->evt.port.ref = htohl(port_ref, sub->swap); | 78 | sub->evt.port.ref = htohl(port_ref, sub->swap); |
| 105 | sub->evt.port.node = htohl(node, sub->swap); | 79 | sub->evt.port.node = htohl(node, sub->swap); |
| 106 | tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base, | 80 | tipc_conn_sendmsg(tn->topsrv, subscriber->conid, NULL, |
| 107 | msg_sect.iov_len); | 81 | msg_sect.iov_base, msg_sect.iov_len); |
| 108 | } | 82 | } |
| 109 | 83 | ||
| 110 | /** | 84 | /** |
| @@ -141,9 +115,11 @@ void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower, | |||
| 141 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); | 115 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); |
| 142 | } | 116 | } |
| 143 | 117 | ||
| 144 | static void subscr_timeout(struct tipc_subscription *sub) | 118 | static void subscr_timeout(unsigned long data) |
| 145 | { | 119 | { |
| 120 | struct tipc_subscription *sub = (struct tipc_subscription *)data; | ||
| 146 | struct tipc_subscriber *subscriber = sub->subscriber; | 121 | struct tipc_subscriber *subscriber = sub->subscriber; |
| 122 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); | ||
| 147 | 123 | ||
| 148 | /* The spin lock per subscriber is used to protect its members */ | 124 | /* The spin lock per subscriber is used to protect its members */ |
| 149 | spin_lock_bh(&subscriber->lock); | 125 | spin_lock_bh(&subscriber->lock); |
| @@ -167,9 +143,8 @@ static void subscr_timeout(struct tipc_subscription *sub) | |||
| 167 | TIPC_SUBSCR_TIMEOUT, 0, 0); | 143 | TIPC_SUBSCR_TIMEOUT, 0, 0); |
| 168 | 144 | ||
| 169 | /* Now destroy subscription */ | 145 | /* Now destroy subscription */ |
| 170 | k_term_timer(&sub->timer); | ||
| 171 | kfree(sub); | 146 | kfree(sub); |
| 172 | atomic_dec(&subscription_count); | 147 | atomic_dec(&tn->subscription_count); |
| 173 | } | 148 | } |
| 174 | 149 | ||
| 175 | /** | 150 | /** |
| @@ -179,10 +154,12 @@ static void subscr_timeout(struct tipc_subscription *sub) | |||
| 179 | */ | 154 | */ |
| 180 | static void subscr_del(struct tipc_subscription *sub) | 155 | static void subscr_del(struct tipc_subscription *sub) |
| 181 | { | 156 | { |
| 157 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); | ||
| 158 | |||
| 182 | tipc_nametbl_unsubscribe(sub); | 159 | tipc_nametbl_unsubscribe(sub); |
| 183 | list_del(&sub->subscription_list); | 160 | list_del(&sub->subscription_list); |
| 184 | kfree(sub); | 161 | kfree(sub); |
| 185 | atomic_dec(&subscription_count); | 162 | atomic_dec(&tn->subscription_count); |
| 186 | } | 163 | } |
| 187 | 164 | ||
| 188 | /** | 165 | /** |
| @@ -190,9 +167,12 @@ static void subscr_del(struct tipc_subscription *sub) | |||
| 190 | * | 167 | * |
| 191 | * Note: Must call it in process context since it might sleep. | 168 | * Note: Must call it in process context since it might sleep. |
| 192 | */ | 169 | */ |
| 193 | static void subscr_terminate(struct tipc_subscriber *subscriber) | 170 | static void subscr_terminate(struct tipc_subscription *sub) |
| 194 | { | 171 | { |
| 195 | tipc_conn_terminate(&topsrv, subscriber->conid); | 172 | struct tipc_subscriber *subscriber = sub->subscriber; |
| 173 | struct tipc_net *tn = net_generic(sub->net, tipc_net_id); | ||
| 174 | |||
| 175 | tipc_conn_terminate(tn->topsrv, subscriber->conid); | ||
| 196 | } | 176 | } |
| 197 | 177 | ||
| 198 | static void subscr_release(struct tipc_subscriber *subscriber) | 178 | static void subscr_release(struct tipc_subscriber *subscriber) |
| @@ -207,8 +187,7 @@ static void subscr_release(struct tipc_subscriber *subscriber) | |||
| 207 | subscription_list) { | 187 | subscription_list) { |
| 208 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 188 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
| 209 | spin_unlock_bh(&subscriber->lock); | 189 | spin_unlock_bh(&subscriber->lock); |
| 210 | k_cancel_timer(&sub->timer); | 190 | del_timer_sync(&sub->timer); |
| 211 | k_term_timer(&sub->timer); | ||
| 212 | spin_lock_bh(&subscriber->lock); | 191 | spin_lock_bh(&subscriber->lock); |
| 213 | } | 192 | } |
| 214 | subscr_del(sub); | 193 | subscr_del(sub); |
| @@ -250,8 +229,7 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
| 250 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 229 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
| 251 | sub->timeout = TIPC_WAIT_FOREVER; | 230 | sub->timeout = TIPC_WAIT_FOREVER; |
| 252 | spin_unlock_bh(&subscriber->lock); | 231 | spin_unlock_bh(&subscriber->lock); |
| 253 | k_cancel_timer(&sub->timer); | 232 | del_timer_sync(&sub->timer); |
| 254 | k_term_timer(&sub->timer); | ||
| 255 | spin_lock_bh(&subscriber->lock); | 233 | spin_lock_bh(&subscriber->lock); |
| 256 | } | 234 | } |
| 257 | subscr_del(sub); | 235 | subscr_del(sub); |
| @@ -262,9 +240,11 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
| 262 | * | 240 | * |
| 263 | * Called with subscriber lock held. | 241 | * Called with subscriber lock held. |
| 264 | */ | 242 | */ |
| 265 | static int subscr_subscribe(struct tipc_subscr *s, | 243 | static int subscr_subscribe(struct net *net, struct tipc_subscr *s, |
| 266 | struct tipc_subscriber *subscriber, | 244 | struct tipc_subscriber *subscriber, |
| 267 | struct tipc_subscription **sub_p) { | 245 | struct tipc_subscription **sub_p) |
| 246 | { | ||
| 247 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
| 268 | struct tipc_subscription *sub; | 248 | struct tipc_subscription *sub; |
| 269 | int swap; | 249 | int swap; |
| 270 | 250 | ||
| @@ -279,7 +259,7 @@ static int subscr_subscribe(struct tipc_subscr *s, | |||
| 279 | } | 259 | } |
| 280 | 260 | ||
| 281 | /* Refuse subscription if global limit exceeded */ | 261 | /* Refuse subscription if global limit exceeded */ |
| 282 | if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { | 262 | if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { |
| 283 | pr_warn("Subscription rejected, limit reached (%u)\n", | 263 | pr_warn("Subscription rejected, limit reached (%u)\n", |
| 284 | TIPC_MAX_SUBSCRIPTIONS); | 264 | TIPC_MAX_SUBSCRIPTIONS); |
| 285 | return -EINVAL; | 265 | return -EINVAL; |
| @@ -293,10 +273,11 @@ static int subscr_subscribe(struct tipc_subscr *s, | |||
| 293 | } | 273 | } |
| 294 | 274 | ||
| 295 | /* Initialize subscription object */ | 275 | /* Initialize subscription object */ |
| 276 | sub->net = net; | ||
| 296 | sub->seq.type = htohl(s->seq.type, swap); | 277 | sub->seq.type = htohl(s->seq.type, swap); |
| 297 | sub->seq.lower = htohl(s->seq.lower, swap); | 278 | sub->seq.lower = htohl(s->seq.lower, swap); |
| 298 | sub->seq.upper = htohl(s->seq.upper, swap); | 279 | sub->seq.upper = htohl(s->seq.upper, swap); |
| 299 | sub->timeout = htohl(s->timeout, swap); | 280 | sub->timeout = msecs_to_jiffies(htohl(s->timeout, swap)); |
| 300 | sub->filter = htohl(s->filter, swap); | 281 | sub->filter = htohl(s->filter, swap); |
| 301 | if ((!(sub->filter & TIPC_SUB_PORTS) == | 282 | if ((!(sub->filter & TIPC_SUB_PORTS) == |
| 302 | !(sub->filter & TIPC_SUB_SERVICE)) || | 283 | !(sub->filter & TIPC_SUB_SERVICE)) || |
| @@ -309,11 +290,10 @@ static int subscr_subscribe(struct tipc_subscr *s, | |||
| 309 | sub->subscriber = subscriber; | 290 | sub->subscriber = subscriber; |
| 310 | sub->swap = swap; | 291 | sub->swap = swap; |
| 311 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | 292 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); |
| 312 | atomic_inc(&subscription_count); | 293 | atomic_inc(&tn->subscription_count); |
| 313 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 294 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
| 314 | k_init_timer(&sub->timer, | 295 | setup_timer(&sub->timer, subscr_timeout, (unsigned long)sub); |
| 315 | (Handler)subscr_timeout, (unsigned long)sub); | 296 | mod_timer(&sub->timer, jiffies + sub->timeout); |
| 316 | k_start_timer(&sub->timer, sub->timeout); | ||
| 317 | } | 297 | } |
| 318 | *sub_p = sub; | 298 | *sub_p = sub; |
| 319 | return 0; | 299 | return 0; |
| @@ -326,16 +306,18 @@ static void subscr_conn_shutdown_event(int conid, void *usr_data) | |||
| 326 | } | 306 | } |
| 327 | 307 | ||
| 328 | /* Handle one request to create a new subscription for the subscriber */ | 308 | /* Handle one request to create a new subscription for the subscriber */ |
| 329 | static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr, | 309 | static void subscr_conn_msg_event(struct net *net, int conid, |
| 330 | void *usr_data, void *buf, size_t len) | 310 | struct sockaddr_tipc *addr, void *usr_data, |
| 311 | void *buf, size_t len) | ||
| 331 | { | 312 | { |
| 332 | struct tipc_subscriber *subscriber = usr_data; | 313 | struct tipc_subscriber *subscriber = usr_data; |
| 333 | struct tipc_subscription *sub = NULL; | 314 | struct tipc_subscription *sub = NULL; |
| 334 | 315 | ||
| 335 | spin_lock_bh(&subscriber->lock); | 316 | spin_lock_bh(&subscriber->lock); |
| 336 | if (subscr_subscribe((struct tipc_subscr *)buf, subscriber, &sub) < 0) { | 317 | if (subscr_subscribe(net, (struct tipc_subscr *)buf, subscriber, |
| 318 | &sub) < 0) { | ||
| 337 | spin_unlock_bh(&subscriber->lock); | 319 | spin_unlock_bh(&subscriber->lock); |
| 338 | subscr_terminate(subscriber); | 320 | subscr_terminate(sub); |
| 339 | return; | 321 | return; |
| 340 | } | 322 | } |
| 341 | if (sub) | 323 | if (sub) |
| @@ -343,7 +325,6 @@ static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr, | |||
| 343 | spin_unlock_bh(&subscriber->lock); | 325 | spin_unlock_bh(&subscriber->lock); |
| 344 | } | 326 | } |
| 345 | 327 | ||
| 346 | |||
| 347 | /* Handle one request to establish a new subscriber */ | 328 | /* Handle one request to establish a new subscriber */ |
| 348 | static void *subscr_named_msg_event(int conid) | 329 | static void *subscr_named_msg_event(int conid) |
| 349 | { | 330 | { |
| @@ -362,12 +343,50 @@ static void *subscr_named_msg_event(int conid) | |||
| 362 | return (void *)subscriber; | 343 | return (void *)subscriber; |
| 363 | } | 344 | } |
| 364 | 345 | ||
| 365 | int tipc_subscr_start(void) | 346 | int tipc_subscr_start(struct net *net) |
| 366 | { | 347 | { |
| 367 | return tipc_server_start(&topsrv); | 348 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 349 | const char name[] = "topology_server"; | ||
| 350 | struct tipc_server *topsrv; | ||
| 351 | struct sockaddr_tipc *saddr; | ||
| 352 | |||
| 353 | saddr = kzalloc(sizeof(*saddr), GFP_ATOMIC); | ||
| 354 | if (!saddr) | ||
| 355 | return -ENOMEM; | ||
| 356 | saddr->family = AF_TIPC; | ||
| 357 | saddr->addrtype = TIPC_ADDR_NAMESEQ; | ||
| 358 | saddr->addr.nameseq.type = TIPC_TOP_SRV; | ||
| 359 | saddr->addr.nameseq.lower = TIPC_TOP_SRV; | ||
| 360 | saddr->addr.nameseq.upper = TIPC_TOP_SRV; | ||
| 361 | saddr->scope = TIPC_NODE_SCOPE; | ||
| 362 | |||
| 363 | topsrv = kzalloc(sizeof(*topsrv), GFP_ATOMIC); | ||
| 364 | if (!topsrv) { | ||
| 365 | kfree(saddr); | ||
| 366 | return -ENOMEM; | ||
| 367 | } | ||
| 368 | topsrv->net = net; | ||
| 369 | topsrv->saddr = saddr; | ||
| 370 | topsrv->imp = TIPC_CRITICAL_IMPORTANCE; | ||
| 371 | topsrv->type = SOCK_SEQPACKET; | ||
| 372 | topsrv->max_rcvbuf_size = sizeof(struct tipc_subscr); | ||
| 373 | topsrv->tipc_conn_recvmsg = subscr_conn_msg_event; | ||
| 374 | topsrv->tipc_conn_new = subscr_named_msg_event; | ||
| 375 | topsrv->tipc_conn_shutdown = subscr_conn_shutdown_event; | ||
| 376 | |||
| 377 | strncpy(topsrv->name, name, strlen(name) + 1); | ||
| 378 | tn->topsrv = topsrv; | ||
| 379 | atomic_set(&tn->subscription_count, 0); | ||
| 380 | |||
| 381 | return tipc_server_start(topsrv); | ||
| 368 | } | 382 | } |
| 369 | 383 | ||
| 370 | void tipc_subscr_stop(void) | 384 | void tipc_subscr_stop(struct net *net) |
| 371 | { | 385 | { |
| 372 | tipc_server_stop(&topsrv); | 386 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 387 | struct tipc_server *topsrv = tn->topsrv; | ||
| 388 | |||
| 389 | tipc_server_stop(topsrv); | ||
| 390 | kfree(topsrv->saddr); | ||
| 391 | kfree(topsrv); | ||
| 373 | } | 392 | } |
