diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/core.c | 3 | ||||
-rw-r--r-- | net/tipc/subscr.c | 199 | ||||
-rw-r--r-- | net/tipc/subscr.h | 4 |
3 files changed, 116 insertions, 90 deletions
diff --git a/net/tipc/core.c b/net/tipc/core.c index 6d6aa5a3c240..3d97386af095 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -164,8 +164,7 @@ int tipc_core_start(void) | |||
164 | tipc_mode = TIPC_NODE_MODE; | 164 | tipc_mode = TIPC_NODE_MODE; |
165 | 165 | ||
166 | if ((res = tipc_handler_start()) || | 166 | if ((res = tipc_handler_start()) || |
167 | (res = tipc_ref_table_init(tipc_max_ports + tipc_max_subscriptions, | 167 | (res = tipc_ref_table_init(tipc_max_ports, tipc_random)) || |
168 | tipc_random)) || | ||
169 | (res = tipc_reg_start()) || | 168 | (res = tipc_reg_start()) || |
170 | (res = tipc_nametbl_init()) || | 169 | (res = tipc_nametbl_init()) || |
171 | (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) || | 170 | (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) || |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index dde23f1e7542..7c62791eb0cc 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -38,23 +38,22 @@ | |||
38 | #include "dbg.h" | 38 | #include "dbg.h" |
39 | #include "subscr.h" | 39 | #include "subscr.h" |
40 | #include "name_table.h" | 40 | #include "name_table.h" |
41 | #include "port.h" | ||
41 | #include "ref.h" | 42 | #include "ref.h" |
42 | 43 | ||
43 | /** | 44 | /** |
44 | * struct subscriber - TIPC network topology subscriber | 45 | * struct subscriber - TIPC network topology subscriber |
45 | * @ref: object reference to subscriber object itself | 46 | * @port_ref: object reference to server port connecting to subscriber |
46 | * @lock: pointer to spinlock controlling access to subscriber object | 47 | * @lock: pointer to spinlock controlling access to subscriber's server port |
47 | * @subscriber_list: adjacent subscribers in top. server's list of subscribers | 48 | * @subscriber_list: adjacent subscribers in top. server's list of subscribers |
48 | * @subscription_list: list of subscription objects for this subscriber | 49 | * @subscription_list: list of subscription objects for this subscriber |
49 | * @port_ref: object reference to port used to communicate with subscriber | ||
50 | */ | 50 | */ |
51 | 51 | ||
52 | struct subscriber { | 52 | struct subscriber { |
53 | u32 ref; | 53 | u32 port_ref; |
54 | spinlock_t *lock; | 54 | spinlock_t *lock; |
55 | struct list_head subscriber_list; | 55 | struct list_head subscriber_list; |
56 | struct list_head subscription_list; | 56 | struct list_head subscription_list; |
57 | u32 port_ref; | ||
58 | }; | 57 | }; |
59 | 58 | ||
60 | /** | 59 | /** |
@@ -91,6 +90,9 @@ static u32 htohl(u32 in, int swap) | |||
91 | 90 | ||
92 | /** | 91 | /** |
93 | * subscr_send_event - send a message containing a tipc_event to the subscriber | 92 | * subscr_send_event - send a message containing a tipc_event to the subscriber |
93 | * | ||
94 | * Note: Must not hold subscriber's server port lock, since tipc_send() will | ||
95 | * try to take the lock if the message is rejected and returned! | ||
94 | */ | 96 | */ |
95 | 97 | ||
96 | static void subscr_send_event(struct subscription *sub, | 98 | static void subscr_send_event(struct subscription *sub, |
@@ -110,7 +112,7 @@ static void subscr_send_event(struct subscription *sub, | |||
110 | sub->evt.found_upper = htohl(found_upper, sub->swap); | 112 | sub->evt.found_upper = htohl(found_upper, sub->swap); |
111 | sub->evt.port.ref = htohl(port_ref, sub->swap); | 113 | sub->evt.port.ref = htohl(port_ref, sub->swap); |
112 | sub->evt.port.node = htohl(node, sub->swap); | 114 | sub->evt.port.node = htohl(node, sub->swap); |
113 | tipc_send(sub->owner->port_ref, 1, &msg_sect); | 115 | tipc_send(sub->server_ref, 1, &msg_sect); |
114 | } | 116 | } |
115 | 117 | ||
116 | /** | 118 | /** |
@@ -163,20 +165,18 @@ void tipc_subscr_report_overlap(struct subscription *sub, | |||
163 | 165 | ||
164 | static void subscr_timeout(struct subscription *sub) | 166 | static void subscr_timeout(struct subscription *sub) |
165 | { | 167 | { |
166 | struct subscriber *subscriber; | 168 | struct port *server_port; |
167 | u32 subscriber_ref; | ||
168 | 169 | ||
169 | /* Validate subscriber reference (in case subscriber is terminating) */ | 170 | /* Validate server port reference (in case subscriber is terminating) */ |
170 | 171 | ||
171 | subscriber_ref = sub->owner->ref; | 172 | server_port = tipc_port_lock(sub->server_ref); |
172 | subscriber = (struct subscriber *)tipc_ref_lock(subscriber_ref); | 173 | if (server_port == NULL) |
173 | if (subscriber == NULL) | ||
174 | return; | 174 | return; |
175 | 175 | ||
176 | /* Validate timeout (in case subscription is being cancelled) */ | 176 | /* Validate timeout (in case subscription is being cancelled) */ |
177 | 177 | ||
178 | if (sub->timeout == TIPC_WAIT_FOREVER) { | 178 | if (sub->timeout == TIPC_WAIT_FOREVER) { |
179 | tipc_ref_unlock(subscriber_ref); | 179 | tipc_port_unlock(server_port); |
180 | return; | 180 | return; |
181 | } | 181 | } |
182 | 182 | ||
@@ -184,19 +184,21 @@ static void subscr_timeout(struct subscription *sub) | |||
184 | 184 | ||
185 | tipc_nametbl_unsubscribe(sub); | 185 | tipc_nametbl_unsubscribe(sub); |
186 | 186 | ||
187 | /* Notify subscriber of timeout, then unlink subscription */ | 187 | /* Unlink subscription from subscriber */ |
188 | 188 | ||
189 | subscr_send_event(sub, | ||
190 | sub->evt.s.seq.lower, | ||
191 | sub->evt.s.seq.upper, | ||
192 | TIPC_SUBSCR_TIMEOUT, | ||
193 | 0, | ||
194 | 0); | ||
195 | list_del(&sub->subscription_list); | 189 | list_del(&sub->subscription_list); |
196 | 190 | ||
191 | /* Release subscriber's server port */ | ||
192 | |||
193 | tipc_port_unlock(server_port); | ||
194 | |||
195 | /* Notify subscriber of timeout */ | ||
196 | |||
197 | subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, | ||
198 | TIPC_SUBSCR_TIMEOUT, 0, 0); | ||
199 | |||
197 | /* Now destroy subscription */ | 200 | /* Now destroy subscription */ |
198 | 201 | ||
199 | tipc_ref_unlock(subscriber_ref); | ||
200 | k_term_timer(&sub->timer); | 202 | k_term_timer(&sub->timer); |
201 | kfree(sub); | 203 | kfree(sub); |
202 | atomic_dec(&topsrv.subscription_count); | 204 | atomic_dec(&topsrv.subscription_count); |
@@ -205,7 +207,7 @@ static void subscr_timeout(struct subscription *sub) | |||
205 | /** | 207 | /** |
206 | * subscr_del - delete a subscription within a subscription list | 208 | * subscr_del - delete a subscription within a subscription list |
207 | * | 209 | * |
208 | * Called with subscriber locked. | 210 | * Called with subscriber port locked. |
209 | */ | 211 | */ |
210 | 212 | ||
211 | static void subscr_del(struct subscription *sub) | 213 | static void subscr_del(struct subscription *sub) |
@@ -219,7 +221,7 @@ static void subscr_del(struct subscription *sub) | |||
219 | /** | 221 | /** |
220 | * subscr_terminate - terminate communication with a subscriber | 222 | * subscr_terminate - terminate communication with a subscriber |
221 | * | 223 | * |
222 | * Called with subscriber locked. Routine must temporarily release this lock | 224 | * Called with subscriber port locked. Routine must temporarily release lock |
223 | * to enable subscription timeout routine(s) to finish without deadlocking; | 225 | * to enable subscription timeout routine(s) to finish without deadlocking; |
224 | * the lock is then reclaimed to allow caller to release it upon return. | 226 | * the lock is then reclaimed to allow caller to release it upon return. |
225 | * (This should work even in the unlikely event some other thread creates | 227 | * (This should work even in the unlikely event some other thread creates |
@@ -229,14 +231,21 @@ static void subscr_del(struct subscription *sub) | |||
229 | 231 | ||
230 | static void subscr_terminate(struct subscriber *subscriber) | 232 | static void subscr_terminate(struct subscriber *subscriber) |
231 | { | 233 | { |
234 | u32 port_ref; | ||
232 | struct subscription *sub; | 235 | struct subscription *sub; |
233 | struct subscription *sub_temp; | 236 | struct subscription *sub_temp; |
234 | 237 | ||
235 | /* Invalidate subscriber reference */ | 238 | /* Invalidate subscriber reference */ |
236 | 239 | ||
237 | tipc_ref_discard(subscriber->ref); | 240 | port_ref = subscriber->port_ref; |
241 | subscriber->port_ref = 0; | ||
238 | spin_unlock_bh(subscriber->lock); | 242 | spin_unlock_bh(subscriber->lock); |
239 | 243 | ||
244 | /* Sever connection to subscriber */ | ||
245 | |||
246 | tipc_shutdown(port_ref); | ||
247 | tipc_deleteport(port_ref); | ||
248 | |||
240 | /* Destroy any existing subscriptions for subscriber */ | 249 | /* Destroy any existing subscriptions for subscriber */ |
241 | 250 | ||
242 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 251 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, |
@@ -250,27 +259,25 @@ static void subscr_terminate(struct subscriber *subscriber) | |||
250 | subscr_del(sub); | 259 | subscr_del(sub); |
251 | } | 260 | } |
252 | 261 | ||
253 | /* Sever connection to subscriber */ | ||
254 | |||
255 | tipc_shutdown(subscriber->port_ref); | ||
256 | tipc_deleteport(subscriber->port_ref); | ||
257 | |||
258 | /* Remove subscriber from topology server's subscriber list */ | 262 | /* Remove subscriber from topology server's subscriber list */ |
259 | 263 | ||
260 | spin_lock_bh(&topsrv.lock); | 264 | spin_lock_bh(&topsrv.lock); |
261 | list_del(&subscriber->subscriber_list); | 265 | list_del(&subscriber->subscriber_list); |
262 | spin_unlock_bh(&topsrv.lock); | 266 | spin_unlock_bh(&topsrv.lock); |
263 | 267 | ||
264 | /* Now destroy subscriber */ | 268 | /* Reclaim subscriber lock */ |
265 | 269 | ||
266 | spin_lock_bh(subscriber->lock); | 270 | spin_lock_bh(subscriber->lock); |
271 | |||
272 | /* Now destroy subscriber */ | ||
273 | |||
267 | kfree(subscriber); | 274 | kfree(subscriber); |
268 | } | 275 | } |
269 | 276 | ||
270 | /** | 277 | /** |
271 | * subscr_cancel - handle subscription cancellation request | 278 | * subscr_cancel - handle subscription cancellation request |
272 | * | 279 | * |
273 | * Called with subscriber locked. Routine must temporarily release this lock | 280 | * Called with subscriber port locked. Routine must temporarily release lock |
274 | * to enable the subscription timeout routine to finish without deadlocking; | 281 | * to enable the subscription timeout routine to finish without deadlocking; |
275 | * the lock is then reclaimed to allow caller to release it upon return. | 282 | * the lock is then reclaimed to allow caller to release it upon return. |
276 | * | 283 | * |
@@ -313,11 +320,11 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
313 | /** | 320 | /** |
314 | * subscr_subscribe - create subscription for subscriber | 321 | * subscr_subscribe - create subscription for subscriber |
315 | * | 322 | * |
316 | * Called with subscriber locked | 323 | * Called with subscriber port locked. |
317 | */ | 324 | */ |
318 | 325 | ||
319 | static void subscr_subscribe(struct tipc_subscr *s, | 326 | static struct subscription *subscr_subscribe(struct tipc_subscr *s, |
320 | struct subscriber *subscriber) | 327 | struct subscriber *subscriber) |
321 | { | 328 | { |
322 | struct subscription *sub; | 329 | struct subscription *sub; |
323 | int swap; | 330 | int swap; |
@@ -331,7 +338,7 @@ static void subscr_subscribe(struct tipc_subscr *s, | |||
331 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { | 338 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { |
332 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); | 339 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); |
333 | subscr_cancel(s, subscriber); | 340 | subscr_cancel(s, subscriber); |
334 | return; | 341 | return NULL; |
335 | } | 342 | } |
336 | 343 | ||
337 | /* Refuse subscription if global limit exceeded */ | 344 | /* Refuse subscription if global limit exceeded */ |
@@ -340,16 +347,16 @@ static void subscr_subscribe(struct tipc_subscr *s, | |||
340 | warn("Subscription rejected, subscription limit reached (%u)\n", | 347 | warn("Subscription rejected, subscription limit reached (%u)\n", |
341 | tipc_max_subscriptions); | 348 | tipc_max_subscriptions); |
342 | subscr_terminate(subscriber); | 349 | subscr_terminate(subscriber); |
343 | return; | 350 | return NULL; |
344 | } | 351 | } |
345 | 352 | ||
346 | /* Allocate subscription object */ | 353 | /* Allocate subscription object */ |
347 | 354 | ||
348 | sub = kzalloc(sizeof(*sub), GFP_ATOMIC); | 355 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); |
349 | if (!sub) { | 356 | if (!sub) { |
350 | warn("Subscription rejected, no memory\n"); | 357 | warn("Subscription rejected, no memory\n"); |
351 | subscr_terminate(subscriber); | 358 | subscr_terminate(subscriber); |
352 | return; | 359 | return NULL; |
353 | } | 360 | } |
354 | 361 | ||
355 | /* Initialize subscription object */ | 362 | /* Initialize subscription object */ |
@@ -365,40 +372,41 @@ static void subscr_subscribe(struct tipc_subscr *s, | |||
365 | warn("Subscription rejected, illegal request\n"); | 372 | warn("Subscription rejected, illegal request\n"); |
366 | kfree(sub); | 373 | kfree(sub); |
367 | subscr_terminate(subscriber); | 374 | subscr_terminate(subscriber); |
368 | return; | 375 | return NULL; |
369 | } | 376 | } |
370 | sub->event_cb = subscr_send_event; | 377 | sub->event_cb = subscr_send_event; |
371 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | ||
372 | INIT_LIST_HEAD(&sub->subscription_list); | ||
373 | INIT_LIST_HEAD(&sub->nameseq_list); | 378 | INIT_LIST_HEAD(&sub->nameseq_list); |
374 | list_add(&sub->subscription_list, &subscriber->subscription_list); | 379 | list_add(&sub->subscription_list, &subscriber->subscription_list); |
380 | sub->server_ref = subscriber->port_ref; | ||
375 | sub->swap = swap; | 381 | sub->swap = swap; |
382 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | ||
376 | atomic_inc(&topsrv.subscription_count); | 383 | atomic_inc(&topsrv.subscription_count); |
377 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 384 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
378 | k_init_timer(&sub->timer, | 385 | k_init_timer(&sub->timer, |
379 | (Handler)subscr_timeout, (unsigned long)sub); | 386 | (Handler)subscr_timeout, (unsigned long)sub); |
380 | k_start_timer(&sub->timer, sub->timeout); | 387 | k_start_timer(&sub->timer, sub->timeout); |
381 | } | 388 | } |
382 | sub->owner = subscriber; | 389 | |
383 | tipc_nametbl_subscribe(sub); | 390 | return sub; |
384 | } | 391 | } |
385 | 392 | ||
386 | /** | 393 | /** |
387 | * subscr_conn_shutdown_event - handle termination request from subscriber | 394 | * subscr_conn_shutdown_event - handle termination request from subscriber |
395 | * | ||
396 | * Called with subscriber's server port unlocked. | ||
388 | */ | 397 | */ |
389 | 398 | ||
390 | static void subscr_conn_shutdown_event(void *usr_handle, | 399 | static void subscr_conn_shutdown_event(void *usr_handle, |
391 | u32 portref, | 400 | u32 port_ref, |
392 | struct sk_buff **buf, | 401 | struct sk_buff **buf, |
393 | unsigned char const *data, | 402 | unsigned char const *data, |
394 | unsigned int size, | 403 | unsigned int size, |
395 | int reason) | 404 | int reason) |
396 | { | 405 | { |
397 | struct subscriber *subscriber; | 406 | struct subscriber *subscriber = usr_handle; |
398 | spinlock_t *subscriber_lock; | 407 | spinlock_t *subscriber_lock; |
399 | 408 | ||
400 | subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle); | 409 | if (tipc_port_lock(port_ref) == NULL) |
401 | if (subscriber == NULL) | ||
402 | return; | 410 | return; |
403 | 411 | ||
404 | subscriber_lock = subscriber->lock; | 412 | subscriber_lock = subscriber->lock; |
@@ -408,6 +416,8 @@ static void subscr_conn_shutdown_event(void *usr_handle, | |||
408 | 416 | ||
409 | /** | 417 | /** |
410 | * subscr_conn_msg_event - handle new subscription request from subscriber | 418 | * subscr_conn_msg_event - handle new subscription request from subscriber |
419 | * | ||
420 | * Called with subscriber's server port unlocked. | ||
411 | */ | 421 | */ |
412 | 422 | ||
413 | static void subscr_conn_msg_event(void *usr_handle, | 423 | static void subscr_conn_msg_event(void *usr_handle, |
@@ -416,20 +426,46 @@ static void subscr_conn_msg_event(void *usr_handle, | |||
416 | const unchar *data, | 426 | const unchar *data, |
417 | u32 size) | 427 | u32 size) |
418 | { | 428 | { |
419 | struct subscriber *subscriber; | 429 | struct subscriber *subscriber = usr_handle; |
420 | spinlock_t *subscriber_lock; | 430 | spinlock_t *subscriber_lock; |
431 | struct subscription *sub; | ||
432 | |||
433 | /* | ||
434 | * Lock subscriber's server port (& make a local copy of lock pointer, | ||
435 | * in case subscriber is deleted while processing subscription request) | ||
436 | */ | ||
421 | 437 | ||
422 | subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle); | 438 | if (tipc_port_lock(port_ref) == NULL) |
423 | if (subscriber == NULL) | ||
424 | return; | 439 | return; |
425 | 440 | ||
426 | subscriber_lock = subscriber->lock; | 441 | subscriber_lock = subscriber->lock; |
427 | if (size != sizeof(struct tipc_subscr)) | ||
428 | subscr_terminate(subscriber); | ||
429 | else | ||
430 | subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
431 | 442 | ||
432 | spin_unlock_bh(subscriber_lock); | 443 | if (size != sizeof(struct tipc_subscr)) { |
444 | subscr_terminate(subscriber); | ||
445 | spin_unlock_bh(subscriber_lock); | ||
446 | } else { | ||
447 | sub = subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
448 | spin_unlock_bh(subscriber_lock); | ||
449 | if (sub != NULL) { | ||
450 | |||
451 | /* | ||
452 | * We must release the server port lock before adding a | ||
453 | * subscription to the name table since TIPC needs to be | ||
454 | * able to (re)acquire the port lock if an event message | ||
455 | * issued by the subscription process is rejected and | ||
456 | * returned. The subscription cannot be deleted while | ||
457 | * it is being added to the name table because: | ||
458 | * a) the single-threading of the native API port code | ||
459 | * ensures the subscription cannot be cancelled and | ||
460 | * the subscriber connection cannot be broken, and | ||
461 | * b) the name table lock ensures the subscription | ||
462 | * timeout code cannot delete the subscription, | ||
463 | * so the subscription object is still protected. | ||
464 | */ | ||
465 | |||
466 | tipc_nametbl_subscribe(sub); | ||
467 | } | ||
468 | } | ||
433 | } | 469 | } |
434 | 470 | ||
435 | /** | 471 | /** |
@@ -445,16 +481,10 @@ static void subscr_named_msg_event(void *usr_handle, | |||
445 | struct tipc_portid const *orig, | 481 | struct tipc_portid const *orig, |
446 | struct tipc_name_seq const *dest) | 482 | struct tipc_name_seq const *dest) |
447 | { | 483 | { |
448 | struct subscriber *subscriber; | 484 | static struct iovec msg_sect = {NULL, 0}; |
449 | struct iovec msg_sect = {NULL, 0}; | ||
450 | spinlock_t *subscriber_lock; | ||
451 | 485 | ||
452 | dbg("subscr_named_msg_event: orig = %x own = %x,\n", | 486 | struct subscriber *subscriber; |
453 | orig->node, tipc_own_addr); | 487 | u32 server_port_ref; |
454 | if (size && (size != sizeof(struct tipc_subscr))) { | ||
455 | warn("Subscriber rejected, invalid subscription size\n"); | ||
456 | return; | ||
457 | } | ||
458 | 488 | ||
459 | /* Create subscriber object */ | 489 | /* Create subscriber object */ |
460 | 490 | ||
@@ -465,18 +495,11 @@ static void subscr_named_msg_event(void *usr_handle, | |||
465 | } | 495 | } |
466 | INIT_LIST_HEAD(&subscriber->subscription_list); | 496 | INIT_LIST_HEAD(&subscriber->subscription_list); |
467 | INIT_LIST_HEAD(&subscriber->subscriber_list); | 497 | INIT_LIST_HEAD(&subscriber->subscriber_list); |
468 | subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock); | ||
469 | if (subscriber->ref == 0) { | ||
470 | warn("Subscriber rejected, reference table exhausted\n"); | ||
471 | kfree(subscriber); | ||
472 | return; | ||
473 | } | ||
474 | spin_unlock_bh(subscriber->lock); | ||
475 | 498 | ||
476 | /* Establish a connection to subscriber */ | 499 | /* Create server port & establish connection to subscriber */ |
477 | 500 | ||
478 | tipc_createport(topsrv.user_ref, | 501 | tipc_createport(topsrv.user_ref, |
479 | (void *)(unsigned long)subscriber->ref, | 502 | subscriber, |
480 | importance, | 503 | importance, |
481 | NULL, | 504 | NULL, |
482 | NULL, | 505 | NULL, |
@@ -488,32 +511,36 @@ static void subscr_named_msg_event(void *usr_handle, | |||
488 | &subscriber->port_ref); | 511 | &subscriber->port_ref); |
489 | if (subscriber->port_ref == 0) { | 512 | if (subscriber->port_ref == 0) { |
490 | warn("Subscriber rejected, unable to create port\n"); | 513 | warn("Subscriber rejected, unable to create port\n"); |
491 | tipc_ref_discard(subscriber->ref); | ||
492 | kfree(subscriber); | 514 | kfree(subscriber); |
493 | return; | 515 | return; |
494 | } | 516 | } |
495 | tipc_connect2port(subscriber->port_ref, orig); | 517 | tipc_connect2port(subscriber->port_ref, orig); |
496 | 518 | ||
519 | /* Lock server port (& save lock address for future use) */ | ||
520 | |||
521 | subscriber->lock = tipc_port_lock(subscriber->port_ref)->publ.lock; | ||
497 | 522 | ||
498 | /* Add subscriber to topology server's subscriber list */ | 523 | /* Add subscriber to topology server's subscriber list */ |
499 | 524 | ||
500 | tipc_ref_lock(subscriber->ref); | ||
501 | spin_lock_bh(&topsrv.lock); | 525 | spin_lock_bh(&topsrv.lock); |
502 | list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); | 526 | list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); |
503 | spin_unlock_bh(&topsrv.lock); | 527 | spin_unlock_bh(&topsrv.lock); |
504 | 528 | ||
505 | /* | 529 | /* Unlock server port */ |
506 | * Subscribe now if message contains a subscription, | ||
507 | * otherwise send an empty response to complete connection handshaking | ||
508 | */ | ||
509 | 530 | ||
510 | subscriber_lock = subscriber->lock; | 531 | server_port_ref = subscriber->port_ref; |
511 | if (size) | 532 | spin_unlock_bh(subscriber->lock); |
512 | subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
513 | else | ||
514 | tipc_send(subscriber->port_ref, 1, &msg_sect); | ||
515 | 533 | ||
516 | spin_unlock_bh(subscriber_lock); | 534 | /* Send an ACK- to complete connection handshaking */ |
535 | |||
536 | tipc_send(server_port_ref, 1, &msg_sect); | ||
537 | |||
538 | /* Handle optional subscription request */ | ||
539 | |||
540 | if (size != 0) { | ||
541 | subscr_conn_msg_event(subscriber, server_port_ref, | ||
542 | buf, data, size); | ||
543 | } | ||
517 | } | 544 | } |
518 | 545 | ||
519 | int tipc_subscr_start(void) | 546 | int tipc_subscr_start(void) |
@@ -572,8 +599,8 @@ void tipc_subscr_stop(void) | |||
572 | list_for_each_entry_safe(subscriber, subscriber_temp, | 599 | list_for_each_entry_safe(subscriber, subscriber_temp, |
573 | &topsrv.subscriber_list, | 600 | &topsrv.subscriber_list, |
574 | subscriber_list) { | 601 | subscriber_list) { |
575 | tipc_ref_lock(subscriber->ref); | ||
576 | subscriber_lock = subscriber->lock; | 602 | subscriber_lock = subscriber->lock; |
603 | spin_lock_bh(subscriber_lock); | ||
577 | subscr_terminate(subscriber); | 604 | subscr_terminate(subscriber); |
578 | spin_unlock_bh(subscriber_lock); | 605 | spin_unlock_bh(subscriber_lock); |
579 | } | 606 | } |
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 3e3e0265146e..b9af687b6368 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h | |||
@@ -49,12 +49,12 @@ typedef void (*tipc_subscr_event) (struct subscription *sub, | |||
49 | * @timeout: duration of subscription (in ms) | 49 | * @timeout: duration of subscription (in ms) |
50 | * @filter: event filtering to be done for subscription | 50 | * @filter: event filtering to be done for subscription |
51 | * @event_cb: routine invoked when a subscription event is detected | 51 | * @event_cb: routine invoked when a subscription event is detected |
52 | * @server_ref: object reference of server port associated with subscription | ||
52 | * @swap: indicates if subscriber uses opposite endianness in its messages | 53 | * @swap: indicates if subscriber uses opposite endianness in its messages |
53 | * @evt: template for events generated by subscription | 54 | * @evt: template for events generated by subscription |
54 | * @subscription_list: adjacent subscriptions in subscriber's subscription list | 55 | * @subscription_list: adjacent subscriptions in subscriber's subscription list |
55 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list | 56 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list |
56 | * @timer_ref: reference to timer governing subscription duration (may be NULL) | 57 | * @timer_ref: reference to timer governing subscription duration (may be NULL) |
57 | * @owner: pointer to subscriber object associated with this subscription | ||
58 | */ | 58 | */ |
59 | 59 | ||
60 | struct subscription { | 60 | struct subscription { |
@@ -62,12 +62,12 @@ struct subscription { | |||
62 | u32 timeout; | 62 | u32 timeout; |
63 | u32 filter; | 63 | u32 filter; |
64 | tipc_subscr_event event_cb; | 64 | tipc_subscr_event event_cb; |
65 | u32 server_ref; | ||
65 | int swap; | 66 | int swap; |
66 | struct tipc_event evt; | 67 | struct tipc_event evt; |
67 | struct list_head subscription_list; | 68 | struct list_head subscription_list; |
68 | struct list_head nameseq_list; | 69 | struct list_head nameseq_list; |
69 | struct timer_list timer; | 70 | struct timer_list timer; |
70 | struct subscriber *owner; | ||
71 | }; | 71 | }; |
72 | 72 | ||
73 | int tipc_subscr_overlap(struct subscription * sub, | 73 | int tipc_subscr_overlap(struct subscription * sub, |