diff options
Diffstat (limited to 'net/tipc/name_table.c')
| -rw-r--r-- | net/tipc/name_table.c | 223 |
1 files changed, 112 insertions, 111 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index d129422fc5c2..049242ea5c38 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
| @@ -71,7 +71,7 @@ struct sub_seq { | |||
| 71 | * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; | 71 | * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; |
| 72 | * sub-sequences are sorted in ascending order | 72 | * sub-sequences are sorted in ascending order |
| 73 | * @alloc: number of sub-sequences currently in array | 73 | * @alloc: number of sub-sequences currently in array |
| 74 | * @first_free: upper bound of highest sub-sequence + 1 | 74 | * @first_free: array index of first unused sub-sequence entry |
| 75 | * @ns_list: links to adjacent name sequences in hash chain | 75 | * @ns_list: links to adjacent name sequences in hash chain |
| 76 | * @subscriptions: list of subscriptions for this 'type' | 76 | * @subscriptions: list of subscriptions for this 'type' |
| 77 | * @lock: spinlock controlling access to name sequence structure | 77 | * @lock: spinlock controlling access to name sequence structure |
| @@ -101,7 +101,7 @@ struct name_table { | |||
| 101 | 101 | ||
| 102 | static struct name_table table = { NULL } ; | 102 | static struct name_table table = { NULL } ; |
| 103 | static atomic_t rsv_publ_ok = ATOMIC_INIT(0); | 103 | static atomic_t rsv_publ_ok = ATOMIC_INIT(0); |
| 104 | rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED; | 104 | DEFINE_RWLOCK(tipc_nametbl_lock); |
| 105 | 105 | ||
| 106 | 106 | ||
| 107 | static int hash(int x) | 107 | static int hash(int x) |
| @@ -117,14 +117,12 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper, | |||
| 117 | u32 scope, u32 node, u32 port_ref, | 117 | u32 scope, u32 node, u32 port_ref, |
| 118 | u32 key) | 118 | u32 key) |
| 119 | { | 119 | { |
| 120 | struct publication *publ = | 120 | struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC); |
| 121 | (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC); | ||
| 122 | if (publ == NULL) { | 121 | if (publ == NULL) { |
| 123 | warn("Memory squeeze; failed to create publication\n"); | 122 | warn("Publication creation failure, no memory\n"); |
| 124 | return NULL; | 123 | return NULL; |
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | memset(publ, 0, sizeof(*publ)); | ||
| 128 | publ->type = type; | 126 | publ->type = type; |
| 129 | publ->lower = lower; | 127 | publ->lower = lower; |
| 130 | publ->upper = upper; | 128 | publ->upper = upper; |
| @@ -144,11 +142,7 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper, | |||
| 144 | 142 | ||
| 145 | static struct sub_seq *tipc_subseq_alloc(u32 cnt) | 143 | static struct sub_seq *tipc_subseq_alloc(u32 cnt) |
| 146 | { | 144 | { |
| 147 | u32 sz = cnt * sizeof(struct sub_seq); | 145 | struct sub_seq *sseq = kcalloc(cnt, sizeof(struct sub_seq), GFP_ATOMIC); |
| 148 | struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC); | ||
| 149 | |||
| 150 | if (sseq) | ||
| 151 | memset(sseq, 0, sz); | ||
| 152 | return sseq; | 146 | return sseq; |
| 153 | } | 147 | } |
| 154 | 148 | ||
| @@ -160,22 +154,20 @@ static struct sub_seq *tipc_subseq_alloc(u32 cnt) | |||
| 160 | 154 | ||
| 161 | static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head) | 155 | static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head) |
| 162 | { | 156 | { |
| 163 | struct name_seq *nseq = | 157 | struct name_seq *nseq = kzalloc(sizeof(*nseq), GFP_ATOMIC); |
| 164 | (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC); | ||
| 165 | struct sub_seq *sseq = tipc_subseq_alloc(1); | 158 | struct sub_seq *sseq = tipc_subseq_alloc(1); |
| 166 | 159 | ||
| 167 | if (!nseq || !sseq) { | 160 | if (!nseq || !sseq) { |
| 168 | warn("Memory squeeze; failed to create name sequence\n"); | 161 | warn("Name sequence creation failed, no memory\n"); |
| 169 | kfree(nseq); | 162 | kfree(nseq); |
| 170 | kfree(sseq); | 163 | kfree(sseq); |
| 171 | return NULL; | 164 | return NULL; |
| 172 | } | 165 | } |
| 173 | 166 | ||
| 174 | memset(nseq, 0, sizeof(*nseq)); | 167 | spin_lock_init(&nseq->lock); |
| 175 | nseq->lock = SPIN_LOCK_UNLOCKED; | ||
| 176 | nseq->type = type; | 168 | nseq->type = type; |
| 177 | nseq->sseqs = sseq; | 169 | nseq->sseqs = sseq; |
| 178 | dbg("tipc_nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", | 170 | dbg("tipc_nameseq_create(): nseq = %p, type %u, ssseqs %p, ff: %u\n", |
| 179 | nseq, type, nseq->sseqs, nseq->first_free); | 171 | nseq, type, nseq->sseqs, nseq->first_free); |
| 180 | nseq->alloc = 1; | 172 | nseq->alloc = 1; |
| 181 | INIT_HLIST_NODE(&nseq->ns_list); | 173 | INIT_HLIST_NODE(&nseq->ns_list); |
| @@ -253,16 +245,16 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, | |||
| 253 | struct sub_seq *sseq; | 245 | struct sub_seq *sseq; |
| 254 | int created_subseq = 0; | 246 | int created_subseq = 0; |
| 255 | 247 | ||
| 256 | assert(nseq->first_free <= nseq->alloc); | ||
| 257 | sseq = nameseq_find_subseq(nseq, lower); | 248 | sseq = nameseq_find_subseq(nseq, lower); |
| 258 | dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n", | 249 | dbg("nameseq_ins: for seq %p, {%u,%u}, found sseq %p\n", |
| 259 | nseq, type, lower, sseq); | 250 | nseq, type, lower, sseq); |
| 260 | if (sseq) { | 251 | if (sseq) { |
| 261 | 252 | ||
| 262 | /* Lower end overlaps existing entry => need an exact match */ | 253 | /* Lower end overlaps existing entry => need an exact match */ |
| 263 | 254 | ||
| 264 | if ((sseq->lower != lower) || (sseq->upper != upper)) { | 255 | if ((sseq->lower != lower) || (sseq->upper != upper)) { |
| 265 | warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); | 256 | warn("Cannot publish {%u,%u,%u}, overlap error\n", |
| 257 | type, lower, upper); | ||
| 266 | return NULL; | 258 | return NULL; |
| 267 | } | 259 | } |
| 268 | } else { | 260 | } else { |
| @@ -277,25 +269,27 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, | |||
| 277 | 269 | ||
| 278 | if ((inspos < nseq->first_free) && | 270 | if ((inspos < nseq->first_free) && |
| 279 | (upper >= nseq->sseqs[inspos].lower)) { | 271 | (upper >= nseq->sseqs[inspos].lower)) { |
| 280 | warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); | 272 | warn("Cannot publish {%u,%u,%u}, overlap error\n", |
| 273 | type, lower, upper); | ||
| 281 | return NULL; | 274 | return NULL; |
| 282 | } | 275 | } |
| 283 | 276 | ||
| 284 | /* Ensure there is space for new sub-sequence */ | 277 | /* Ensure there is space for new sub-sequence */ |
| 285 | 278 | ||
| 286 | if (nseq->first_free == nseq->alloc) { | 279 | if (nseq->first_free == nseq->alloc) { |
| 287 | struct sub_seq *sseqs = nseq->sseqs; | 280 | struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2); |
| 288 | nseq->sseqs = tipc_subseq_alloc(nseq->alloc * 2); | 281 | |
| 289 | if (nseq->sseqs != NULL) { | 282 | if (!sseqs) { |
| 290 | memcpy(nseq->sseqs, sseqs, | 283 | warn("Cannot publish {%u,%u,%u}, no memory\n", |
| 291 | nseq->alloc * sizeof (struct sub_seq)); | 284 | type, lower, upper); |
| 292 | kfree(sseqs); | ||
| 293 | dbg("Allocated %u sseqs\n", nseq->alloc); | ||
| 294 | nseq->alloc *= 2; | ||
| 295 | } else { | ||
| 296 | warn("Memory squeeze; failed to create sub-sequence\n"); | ||
| 297 | return NULL; | 285 | return NULL; |
| 298 | } | 286 | } |
| 287 | dbg("Allocated %u more sseqs\n", nseq->alloc); | ||
| 288 | memcpy(sseqs, nseq->sseqs, | ||
| 289 | nseq->alloc * sizeof(struct sub_seq)); | ||
| 290 | kfree(nseq->sseqs); | ||
| 291 | nseq->sseqs = sseqs; | ||
| 292 | nseq->alloc *= 2; | ||
| 299 | } | 293 | } |
| 300 | dbg("Have %u sseqs for type %u\n", nseq->alloc, type); | 294 | dbg("Have %u sseqs for type %u\n", nseq->alloc, type); |
| 301 | 295 | ||
| @@ -311,7 +305,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, | |||
| 311 | sseq->upper = upper; | 305 | sseq->upper = upper; |
| 312 | created_subseq = 1; | 306 | created_subseq = 1; |
| 313 | } | 307 | } |
| 314 | dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n", | 308 | dbg("inserting {%u,%u,%u} from <0x%x:%u> into sseq %p(%u,%u) of seq %p\n", |
| 315 | type, lower, upper, node, port, sseq, | 309 | type, lower, upper, node, port, sseq, |
| 316 | sseq->lower, sseq->upper, nseq); | 310 | sseq->lower, sseq->upper, nseq); |
| 317 | 311 | ||
| @@ -320,7 +314,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, | |||
| 320 | publ = publ_create(type, lower, upper, scope, node, port, key); | 314 | publ = publ_create(type, lower, upper, scope, node, port, key); |
| 321 | if (!publ) | 315 | if (!publ) |
| 322 | return NULL; | 316 | return NULL; |
| 323 | dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n", | 317 | dbg("inserting publ %p, node=0x%x publ->node=0x%x, subscr->node=%p\n", |
| 324 | publ, node, publ->node, publ->subscr.node); | 318 | publ, node, publ->node, publ->subscr.node); |
| 325 | 319 | ||
| 326 | if (!sseq->zone_list) | 320 | if (!sseq->zone_list) |
| @@ -367,45 +361,47 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, | |||
| 367 | 361 | ||
| 368 | /** | 362 | /** |
| 369 | * tipc_nameseq_remove_publ - | 363 | * tipc_nameseq_remove_publ - |
| 364 | * | ||
| 365 | * NOTE: There may be cases where TIPC is asked to remove a publication | ||
| 366 | * that is not in the name table. For example, if another node issues a | ||
| 367 | * publication for a name sequence that overlaps an existing name sequence | ||
| 368 | * the publication will not be recorded, which means the publication won't | ||
| 369 | * be found when the name sequence is later withdrawn by that node. | ||
| 370 | * A failed withdraw request simply returns a failure indication and lets the | ||
| 371 | * caller issue any error or warning messages associated with such a problem. | ||
| 370 | */ | 372 | */ |
| 371 | 373 | ||
| 372 | static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst, | 374 | static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst, |
| 373 | u32 node, u32 ref, u32 key) | 375 | u32 node, u32 ref, u32 key) |
| 374 | { | 376 | { |
| 375 | struct publication *publ; | 377 | struct publication *publ; |
| 378 | struct publication *curr; | ||
| 376 | struct publication *prev; | 379 | struct publication *prev; |
| 377 | struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); | 380 | struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); |
| 378 | struct sub_seq *free; | 381 | struct sub_seq *free; |
| 379 | struct subscription *s, *st; | 382 | struct subscription *s, *st; |
| 380 | int removed_subseq = 0; | 383 | int removed_subseq = 0; |
| 381 | 384 | ||
| 382 | assert(nseq); | 385 | if (!sseq) |
| 383 | |||
| 384 | if (!sseq) { | ||
| 385 | int i; | ||
| 386 | |||
| 387 | warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst); | ||
| 388 | assert(nseq->sseqs); | ||
| 389 | dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n", | ||
| 390 | nseq->sseqs, nseq, nseq->alloc, | ||
| 391 | nseq->first_free); | ||
| 392 | for (i = 0; i < nseq->first_free; i++) { | ||
| 393 | dbg("Subseq %u(%x): lower = %u,upper = %u\n", | ||
| 394 | i, &nseq->sseqs[i], nseq->sseqs[i].lower, | ||
| 395 | nseq->sseqs[i].upper); | ||
| 396 | } | ||
| 397 | return NULL; | 386 | return NULL; |
| 398 | } | 387 | |
| 399 | dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n", | 388 | dbg("tipc_nameseq_remove_publ: seq: %p, sseq %p, {%u,%u}, key %u\n", |
| 400 | nseq, sseq, nseq->type, inst, key); | 389 | nseq, sseq, nseq->type, inst, key); |
| 401 | 390 | ||
| 391 | /* Remove publication from zone scope list */ | ||
| 392 | |||
| 402 | prev = sseq->zone_list; | 393 | prev = sseq->zone_list; |
| 403 | publ = sseq->zone_list->zone_list_next; | 394 | publ = sseq->zone_list->zone_list_next; |
| 404 | while ((publ->key != key) || (publ->ref != ref) || | 395 | while ((publ->key != key) || (publ->ref != ref) || |
| 405 | (publ->node && (publ->node != node))) { | 396 | (publ->node && (publ->node != node))) { |
| 406 | prev = publ; | 397 | prev = publ; |
| 407 | publ = publ->zone_list_next; | 398 | publ = publ->zone_list_next; |
| 408 | assert(prev != sseq->zone_list); | 399 | if (prev == sseq->zone_list) { |
| 400 | |||
| 401 | /* Prevent endless loop if publication not found */ | ||
| 402 | |||
| 403 | return NULL; | ||
| 404 | } | ||
| 409 | } | 405 | } |
| 410 | if (publ != sseq->zone_list) | 406 | if (publ != sseq->zone_list) |
| 411 | prev->zone_list_next = publ->zone_list_next; | 407 | prev->zone_list_next = publ->zone_list_next; |
| @@ -416,14 +412,24 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i | |||
| 416 | sseq->zone_list = NULL; | 412 | sseq->zone_list = NULL; |
| 417 | } | 413 | } |
| 418 | 414 | ||
| 415 | /* Remove publication from cluster scope list, if present */ | ||
| 416 | |||
| 419 | if (in_own_cluster(node)) { | 417 | if (in_own_cluster(node)) { |
| 420 | prev = sseq->cluster_list; | 418 | prev = sseq->cluster_list; |
| 421 | publ = sseq->cluster_list->cluster_list_next; | 419 | curr = sseq->cluster_list->cluster_list_next; |
| 422 | while ((publ->key != key) || (publ->ref != ref) || | 420 | while (curr != publ) { |
| 423 | (publ->node && (publ->node != node))) { | 421 | prev = curr; |
| 424 | prev = publ; | 422 | curr = curr->cluster_list_next; |
| 425 | publ = publ->cluster_list_next; | 423 | if (prev == sseq->cluster_list) { |
| 426 | assert(prev != sseq->cluster_list); | 424 | |
| 425 | /* Prevent endless loop for malformed list */ | ||
| 426 | |||
| 427 | err("Unable to de-list cluster publication\n" | ||
| 428 | "{%u%u}, node=0x%x, ref=%u, key=%u)\n", | ||
| 429 | publ->type, publ->lower, publ->node, | ||
| 430 | publ->ref, publ->key); | ||
| 431 | goto end_cluster; | ||
| 432 | } | ||
| 427 | } | 433 | } |
| 428 | if (publ != sseq->cluster_list) | 434 | if (publ != sseq->cluster_list) |
| 429 | prev->cluster_list_next = publ->cluster_list_next; | 435 | prev->cluster_list_next = publ->cluster_list_next; |
| @@ -434,15 +440,26 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i | |||
| 434 | sseq->cluster_list = NULL; | 440 | sseq->cluster_list = NULL; |
| 435 | } | 441 | } |
| 436 | } | 442 | } |
| 443 | end_cluster: | ||
| 444 | |||
| 445 | /* Remove publication from node scope list, if present */ | ||
| 437 | 446 | ||
| 438 | if (node == tipc_own_addr) { | 447 | if (node == tipc_own_addr) { |
| 439 | prev = sseq->node_list; | 448 | prev = sseq->node_list; |
| 440 | publ = sseq->node_list->node_list_next; | 449 | curr = sseq->node_list->node_list_next; |
| 441 | while ((publ->key != key) || (publ->ref != ref) || | 450 | while (curr != publ) { |
| 442 | (publ->node && (publ->node != node))) { | 451 | prev = curr; |
| 443 | prev = publ; | 452 | curr = curr->node_list_next; |
| 444 | publ = publ->node_list_next; | 453 | if (prev == sseq->node_list) { |
| 445 | assert(prev != sseq->node_list); | 454 | |
| 455 | /* Prevent endless loop for malformed list */ | ||
| 456 | |||
| 457 | err("Unable to de-list node publication\n" | ||
| 458 | "{%u%u}, node=0x%x, ref=%u, key=%u)\n", | ||
| 459 | publ->type, publ->lower, publ->node, | ||
| 460 | publ->ref, publ->key); | ||
| 461 | goto end_node; | ||
| 462 | } | ||
| 446 | } | 463 | } |
| 447 | if (publ != sseq->node_list) | 464 | if (publ != sseq->node_list) |
| 448 | prev->node_list_next = publ->node_list_next; | 465 | prev->node_list_next = publ->node_list_next; |
| @@ -453,22 +470,18 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i | |||
| 453 | sseq->node_list = NULL; | 470 | sseq->node_list = NULL; |
| 454 | } | 471 | } |
| 455 | } | 472 | } |
| 456 | assert(!publ->node || (publ->node == node)); | 473 | end_node: |
| 457 | assert(publ->ref == ref); | ||
| 458 | assert(publ->key == key); | ||
| 459 | 474 | ||
| 460 | /* | 475 | /* Contract subseq list if no more publications for that subseq */ |
| 461 | * Contract subseq list if no more publications: | 476 | |
| 462 | */ | 477 | if (!sseq->zone_list) { |
| 463 | if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) { | ||
| 464 | free = &nseq->sseqs[nseq->first_free--]; | 478 | free = &nseq->sseqs[nseq->first_free--]; |
| 465 | memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); | 479 | memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); |
| 466 | removed_subseq = 1; | 480 | removed_subseq = 1; |
| 467 | } | 481 | } |
| 468 | 482 | ||
| 469 | /* | 483 | /* Notify any waiting subscriptions */ |
| 470 | * Any subscriptions waiting ? | 484 | |
| 471 | */ | ||
| 472 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | 485 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { |
| 473 | tipc_subscr_report_overlap(s, | 486 | tipc_subscr_report_overlap(s, |
| 474 | publ->lower, | 487 | publ->lower, |
| @@ -478,6 +491,7 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i | |||
| 478 | publ->node, | 491 | publ->node, |
| 479 | removed_subseq); | 492 | removed_subseq); |
| 480 | } | 493 | } |
| 494 | |||
| 481 | return publ; | 495 | return publ; |
| 482 | } | 496 | } |
| 483 | 497 | ||
| @@ -530,7 +544,7 @@ static struct name_seq *nametbl_find_seq(u32 type) | |||
| 530 | seq_head = &table.types[hash(type)]; | 544 | seq_head = &table.types[hash(type)]; |
| 531 | hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { | 545 | hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { |
| 532 | if (ns->type == type) { | 546 | if (ns->type == type) { |
| 533 | dbg("found %x\n", ns); | 547 | dbg("found %p\n", ns); |
| 534 | return ns; | 548 | return ns; |
| 535 | } | 549 | } |
| 536 | } | 550 | } |
| @@ -543,22 +557,21 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, | |||
| 543 | { | 557 | { |
| 544 | struct name_seq *seq = nametbl_find_seq(type); | 558 | struct name_seq *seq = nametbl_find_seq(type); |
| 545 | 559 | ||
| 546 | dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq); | 560 | dbg("tipc_nametbl_insert_publ: {%u,%u,%u} found %p\n", type, lower, upper, seq); |
| 547 | if (lower > upper) { | 561 | if (lower > upper) { |
| 548 | warn("Failed to publish illegal <%u,%u,%u>\n", | 562 | warn("Failed to publish illegal {%u,%u,%u}\n", |
| 549 | type, lower, upper); | 563 | type, lower, upper); |
| 550 | return NULL; | 564 | return NULL; |
| 551 | } | 565 | } |
| 552 | 566 | ||
| 553 | dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); | 567 | dbg("Publishing {%u,%u,%u} from 0x%x\n", type, lower, upper, node); |
| 554 | if (!seq) { | 568 | if (!seq) { |
| 555 | seq = tipc_nameseq_create(type, &table.types[hash(type)]); | 569 | seq = tipc_nameseq_create(type, &table.types[hash(type)]); |
| 556 | dbg("tipc_nametbl_insert_publ: created %x\n", seq); | 570 | dbg("tipc_nametbl_insert_publ: created %p\n", seq); |
| 557 | } | 571 | } |
| 558 | if (!seq) | 572 | if (!seq) |
| 559 | return NULL; | 573 | return NULL; |
| 560 | 574 | ||
| 561 | assert(seq->type == type); | ||
| 562 | return tipc_nameseq_insert_publ(seq, type, lower, upper, | 575 | return tipc_nameseq_insert_publ(seq, type, lower, upper, |
| 563 | scope, node, port, key); | 576 | scope, node, port, key); |
| 564 | } | 577 | } |
| @@ -572,7 +585,7 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, | |||
| 572 | if (!seq) | 585 | if (!seq) |
| 573 | return NULL; | 586 | return NULL; |
| 574 | 587 | ||
| 575 | dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); | 588 | dbg("Withdrawing {%u,%u} from 0x%x\n", type, lower, node); |
| 576 | publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); | 589 | publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); |
| 577 | 590 | ||
| 578 | if (!seq->first_free && list_empty(&seq->subscriptions)) { | 591 | if (!seq->first_free && list_empty(&seq->subscriptions)) { |
| @@ -738,12 +751,12 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, | |||
| 738 | struct publication *publ; | 751 | struct publication *publ; |
| 739 | 752 | ||
| 740 | if (table.local_publ_count >= tipc_max_publications) { | 753 | if (table.local_publ_count >= tipc_max_publications) { |
| 741 | warn("Failed publish: max %u local publication\n", | 754 | warn("Publication failed, local publication limit reached (%u)\n", |
| 742 | tipc_max_publications); | 755 | tipc_max_publications); |
| 743 | return NULL; | 756 | return NULL; |
| 744 | } | 757 | } |
| 745 | if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { | 758 | if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { |
| 746 | warn("Failed to publish reserved name <%u,%u,%u>\n", | 759 | warn("Publication failed, reserved name {%u,%u,%u}\n", |
| 747 | type, lower, upper); | 760 | type, lower, upper); |
| 748 | return NULL; | 761 | return NULL; |
| 749 | } | 762 | } |
| @@ -767,10 +780,10 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) | |||
| 767 | { | 780 | { |
| 768 | struct publication *publ; | 781 | struct publication *publ; |
| 769 | 782 | ||
| 770 | dbg("tipc_nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); | 783 | dbg("tipc_nametbl_withdraw: {%u,%u}, key=%u\n", type, lower, key); |
| 771 | write_lock_bh(&tipc_nametbl_lock); | 784 | write_lock_bh(&tipc_nametbl_lock); |
| 772 | publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); | 785 | publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); |
| 773 | if (publ) { | 786 | if (likely(publ)) { |
| 774 | table.local_publ_count--; | 787 | table.local_publ_count--; |
| 775 | if (publ->scope != TIPC_NODE_SCOPE) | 788 | if (publ->scope != TIPC_NODE_SCOPE) |
| 776 | tipc_named_withdraw(publ); | 789 | tipc_named_withdraw(publ); |
| @@ -780,6 +793,9 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) | |||
| 780 | return 1; | 793 | return 1; |
| 781 | } | 794 | } |
| 782 | write_unlock_bh(&tipc_nametbl_lock); | 795 | write_unlock_bh(&tipc_nametbl_lock); |
| 796 | err("Unable to remove local publication\n" | ||
| 797 | "(type=%u, lower=%u, ref=%u, key=%u)\n", | ||
| 798 | type, lower, ref, key); | ||
| 783 | return 0; | 799 | return 0; |
| 784 | } | 800 | } |
| 785 | 801 | ||
| @@ -787,8 +803,7 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) | |||
| 787 | * tipc_nametbl_subscribe - add a subscription object to the name table | 803 | * tipc_nametbl_subscribe - add a subscription object to the name table |
| 788 | */ | 804 | */ |
| 789 | 805 | ||
| 790 | void | 806 | void tipc_nametbl_subscribe(struct subscription *s) |
| 791 | tipc_nametbl_subscribe(struct subscription *s) | ||
| 792 | { | 807 | { |
| 793 | u32 type = s->seq.type; | 808 | u32 type = s->seq.type; |
| 794 | struct name_seq *seq; | 809 | struct name_seq *seq; |
| @@ -800,11 +815,13 @@ tipc_nametbl_subscribe(struct subscription *s) | |||
| 800 | } | 815 | } |
| 801 | if (seq){ | 816 | if (seq){ |
| 802 | spin_lock_bh(&seq->lock); | 817 | spin_lock_bh(&seq->lock); |
| 803 | dbg("tipc_nametbl_subscribe:found %x for <%u,%u,%u>\n", | 818 | dbg("tipc_nametbl_subscribe:found %p for {%u,%u,%u}\n", |
| 804 | seq, type, s->seq.lower, s->seq.upper); | 819 | seq, type, s->seq.lower, s->seq.upper); |
| 805 | assert(seq->type == type); | ||
| 806 | tipc_nameseq_subscribe(seq, s); | 820 | tipc_nameseq_subscribe(seq, s); |
| 807 | spin_unlock_bh(&seq->lock); | 821 | spin_unlock_bh(&seq->lock); |
| 822 | } else { | ||
| 823 | warn("Failed to create subscription for {%u,%u,%u}\n", | ||
| 824 | s->seq.type, s->seq.lower, s->seq.upper); | ||
| 808 | } | 825 | } |
| 809 | write_unlock_bh(&tipc_nametbl_lock); | 826 | write_unlock_bh(&tipc_nametbl_lock); |
| 810 | } | 827 | } |
| @@ -813,8 +830,7 @@ tipc_nametbl_subscribe(struct subscription *s) | |||
| 813 | * tipc_nametbl_unsubscribe - remove a subscription object from name table | 830 | * tipc_nametbl_unsubscribe - remove a subscription object from name table |
| 814 | */ | 831 | */ |
| 815 | 832 | ||
| 816 | void | 833 | void tipc_nametbl_unsubscribe(struct subscription *s) |
| 817 | tipc_nametbl_unsubscribe(struct subscription *s) | ||
| 818 | { | 834 | { |
| 819 | struct name_seq *seq; | 835 | struct name_seq *seq; |
| 820 | 836 | ||
| @@ -1036,7 +1052,7 @@ int tipc_nametbl_init(void) | |||
| 1036 | { | 1052 | { |
| 1037 | int array_size = sizeof(struct hlist_head) * tipc_nametbl_size; | 1053 | int array_size = sizeof(struct hlist_head) * tipc_nametbl_size; |
| 1038 | 1054 | ||
| 1039 | table.types = (struct hlist_head *)kmalloc(array_size, GFP_ATOMIC); | 1055 | table.types = kmalloc(array_size, GFP_ATOMIC); |
| 1040 | if (!table.types) | 1056 | if (!table.types) |
| 1041 | return -ENOMEM; | 1057 | return -ENOMEM; |
| 1042 | 1058 | ||
| @@ -1049,35 +1065,20 @@ int tipc_nametbl_init(void) | |||
| 1049 | 1065 | ||
| 1050 | void tipc_nametbl_stop(void) | 1066 | void tipc_nametbl_stop(void) |
| 1051 | { | 1067 | { |
| 1052 | struct hlist_head *seq_head; | ||
| 1053 | struct hlist_node *seq_node; | ||
| 1054 | struct hlist_node *tmp; | ||
| 1055 | struct name_seq *seq; | ||
| 1056 | u32 i; | 1068 | u32 i; |
| 1057 | 1069 | ||
| 1058 | if (!table.types) | 1070 | if (!table.types) |
| 1059 | return; | 1071 | return; |
| 1060 | 1072 | ||
| 1073 | /* Verify name table is empty, then release it */ | ||
| 1074 | |||
| 1061 | write_lock_bh(&tipc_nametbl_lock); | 1075 | write_lock_bh(&tipc_nametbl_lock); |
| 1062 | for (i = 0; i < tipc_nametbl_size; i++) { | 1076 | for (i = 0; i < tipc_nametbl_size; i++) { |
| 1063 | seq_head = &table.types[i]; | 1077 | if (!hlist_empty(&table.types[i])) |
| 1064 | hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) { | 1078 | err("tipc_nametbl_stop(): hash chain %u is non-null\n", i); |
| 1065 | struct sub_seq *sseq = seq->sseqs; | ||
| 1066 | |||
| 1067 | for (; sseq != &seq->sseqs[seq->first_free]; sseq++) { | ||
| 1068 | struct publication *publ = sseq->zone_list; | ||
| 1069 | assert(publ); | ||
| 1070 | do { | ||
| 1071 | struct publication *next = | ||
| 1072 | publ->zone_list_next; | ||
| 1073 | kfree(publ); | ||
| 1074 | publ = next; | ||
| 1075 | } | ||
| 1076 | while (publ != sseq->zone_list); | ||
| 1077 | } | ||
| 1078 | } | ||
| 1079 | } | 1079 | } |
| 1080 | kfree(table.types); | 1080 | kfree(table.types); |
| 1081 | table.types = NULL; | 1081 | table.types = NULL; |
| 1082 | write_unlock_bh(&tipc_nametbl_lock); | 1082 | write_unlock_bh(&tipc_nametbl_lock); |
| 1083 | } | 1083 | } |
| 1084 | |||
