Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
name_table.c
Go to the documentation of this file.
1 /*
2  * net/tipc/name_table.c: TIPC name table code
3  *
4  * Copyright (c) 2000-2006, Ericsson AB
5  * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. Neither the names of the copyright holders nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * Alternatively, this software may be distributed under the terms of the
21  * GNU General Public License ("GPL") version 2 as published by the Free
22  * Software Foundation.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include "core.h"
38 #include "config.h"
39 #include "name_table.h"
40 #include "name_distr.h"
41 #include "subscr.h"
42 #include "port.h"
43 
44 #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */
45 
59 struct name_info {
66 };
67 
74 struct sub_seq {
77  struct name_info *info;
78 };
79 
91 struct name_seq {
93  struct sub_seq *sseqs;
99 };
100 
107 struct name_table {
108  struct hlist_head *types;
110 };
111 
112 static struct name_table table;
113 DEFINE_RWLOCK(tipc_nametbl_lock);
114 
115 static int hash(int x)
116 {
117  return x & (TIPC_NAMETBL_SIZE - 1);
118 }
119 
123 static struct publication *publ_create(u32 type, u32 lower, u32 upper,
124  u32 scope, u32 node, u32 port_ref,
125  u32 key)
126 {
127  struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC);
128  if (publ == NULL) {
129  pr_warn("Publication creation failure, no memory\n");
130  return NULL;
131  }
132 
133  publ->type = type;
134  publ->lower = lower;
135  publ->upper = upper;
136  publ->scope = scope;
137  publ->node = node;
138  publ->ref = port_ref;
139  publ->key = key;
140  INIT_LIST_HEAD(&publ->local_list);
141  INIT_LIST_HEAD(&publ->pport_list);
142  INIT_LIST_HEAD(&publ->subscr.nodesub_list);
143  return publ;
144 }
145 
149 static struct sub_seq *tipc_subseq_alloc(u32 cnt)
150 {
151  struct sub_seq *sseq = kcalloc(cnt, sizeof(struct sub_seq), GFP_ATOMIC);
152  return sseq;
153 }
154 
160 static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
161 {
162  struct name_seq *nseq = kzalloc(sizeof(*nseq), GFP_ATOMIC);
163  struct sub_seq *sseq = tipc_subseq_alloc(1);
164 
165  if (!nseq || !sseq) {
166  pr_warn("Name sequence creation failed, no memory\n");
167  kfree(nseq);
168  kfree(sseq);
169  return NULL;
170  }
171 
172  spin_lock_init(&nseq->lock);
173  nseq->type = type;
174  nseq->sseqs = sseq;
175  nseq->alloc = 1;
176  INIT_HLIST_NODE(&nseq->ns_list);
177  INIT_LIST_HEAD(&nseq->subscriptions);
178  hlist_add_head(&nseq->ns_list, seq_head);
179  return nseq;
180 }
181 
182 /*
183  * nameseq_delete_empty - deletes a name sequence structure if now unused
184  */
185 static void nameseq_delete_empty(struct name_seq *seq)
186 {
187  if (!seq->first_free && list_empty(&seq->subscriptions)) {
188  hlist_del_init(&seq->ns_list);
189  kfree(seq->sseqs);
190  kfree(seq);
191  }
192 }
193 
199 static struct sub_seq *nameseq_find_subseq(struct name_seq *nseq,
200  u32 instance)
201 {
202  struct sub_seq *sseqs = nseq->sseqs;
203  int low = 0;
204  int high = nseq->first_free - 1;
205  int mid;
206 
207  while (low <= high) {
208  mid = (low + high) / 2;
209  if (instance < sseqs[mid].lower)
210  high = mid - 1;
211  else if (instance > sseqs[mid].upper)
212  low = mid + 1;
213  else
214  return &sseqs[mid];
215  }
216  return NULL;
217 }
218 
228 static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance)
229 {
230  struct sub_seq *sseqs = nseq->sseqs;
231  int low = 0;
232  int high = nseq->first_free - 1;
233  int mid;
234 
235  while (low <= high) {
236  mid = (low + high) / 2;
237  if (instance < sseqs[mid].lower)
238  high = mid - 1;
239  else if (instance > sseqs[mid].upper)
240  low = mid + 1;
241  else
242  return mid;
243  }
244  return low;
245 }
246 
250 static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
251  u32 type, u32 lower, u32 upper,
252  u32 scope, u32 node, u32 port, u32 key)
253 {
254  struct tipc_subscription *s;
255  struct tipc_subscription *st;
256  struct publication *publ;
257  struct sub_seq *sseq;
258  struct name_info *info;
259  int created_subseq = 0;
260 
261  sseq = nameseq_find_subseq(nseq, lower);
262  if (sseq) {
263 
264  /* Lower end overlaps existing entry => need an exact match */
265  if ((sseq->lower != lower) || (sseq->upper != upper)) {
266  pr_warn("Cannot publish {%u,%u,%u}, overlap error\n",
267  type, lower, upper);
268  return NULL;
269  }
270 
271  info = sseq->info;
272 
273  /* Check if an identical publication already exists */
274  list_for_each_entry(publ, &info->zone_list, zone_list) {
275  if ((publ->ref == port) && (publ->key == key) &&
276  (!publ->node || (publ->node == node)))
277  return NULL;
278  }
279  } else {
280  u32 inspos;
281  struct sub_seq *freesseq;
282 
283  /* Find where lower end should be inserted */
284  inspos = nameseq_locate_subseq(nseq, lower);
285 
286  /* Fail if upper end overlaps into an existing entry */
287  if ((inspos < nseq->first_free) &&
288  (upper >= nseq->sseqs[inspos].lower)) {
289  pr_warn("Cannot publish {%u,%u,%u}, overlap error\n",
290  type, lower, upper);
291  return NULL;
292  }
293 
294  /* Ensure there is space for new sub-sequence */
295  if (nseq->first_free == nseq->alloc) {
296  struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2);
297 
298  if (!sseqs) {
299  pr_warn("Cannot publish {%u,%u,%u}, no memory\n",
300  type, lower, upper);
301  return NULL;
302  }
303  memcpy(sseqs, nseq->sseqs,
304  nseq->alloc * sizeof(struct sub_seq));
305  kfree(nseq->sseqs);
306  nseq->sseqs = sseqs;
307  nseq->alloc *= 2;
308  }
309 
310  info = kzalloc(sizeof(*info), GFP_ATOMIC);
311  if (!info) {
312  pr_warn("Cannot publish {%u,%u,%u}, no memory\n",
313  type, lower, upper);
314  return NULL;
315  }
316 
317  INIT_LIST_HEAD(&info->node_list);
318  INIT_LIST_HEAD(&info->cluster_list);
319  INIT_LIST_HEAD(&info->zone_list);
320 
321  /* Insert new sub-sequence */
322  sseq = &nseq->sseqs[inspos];
323  freesseq = &nseq->sseqs[nseq->first_free];
324  memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof(*sseq));
325  memset(sseq, 0, sizeof(*sseq));
326  nseq->first_free++;
327  sseq->lower = lower;
328  sseq->upper = upper;
329  sseq->info = info;
330  created_subseq = 1;
331  }
332 
333  /* Insert a publication */
334  publ = publ_create(type, lower, upper, scope, node, port, key);
335  if (!publ)
336  return NULL;
337 
338  list_add(&publ->zone_list, &info->zone_list);
339  info->zone_list_size++;
340 
341  if (in_own_cluster(node)) {
342  list_add(&publ->cluster_list, &info->cluster_list);
343  info->cluster_list_size++;
344  }
345 
346  if (in_own_node(node)) {
347  list_add(&publ->node_list, &info->node_list);
348  info->node_list_size++;
349  }
350 
351  /* Any subscriptions waiting for notification? */
352  list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
354  publ->lower,
355  publ->upper,
357  publ->ref,
358  publ->node,
359  created_subseq);
360  }
361  return publ;
362 }
363 
375 static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
376  u32 node, u32 ref, u32 key)
377 {
378  struct publication *publ;
379  struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
380  struct name_info *info;
381  struct sub_seq *free;
382  struct tipc_subscription *s, *st;
383  int removed_subseq = 0;
384 
385  if (!sseq)
386  return NULL;
387 
388  info = sseq->info;
389 
390  /* Locate publication, if it exists */
391  list_for_each_entry(publ, &info->zone_list, zone_list) {
392  if ((publ->key == key) && (publ->ref == ref) &&
393  (!publ->node || (publ->node == node)))
394  goto found;
395  }
396  return NULL;
397 
398 found:
399  /* Remove publication from zone scope list */
400  list_del(&publ->zone_list);
401  info->zone_list_size--;
402 
403  /* Remove publication from cluster scope list, if present */
404  if (in_own_cluster(node)) {
405  list_del(&publ->cluster_list);
406  info->cluster_list_size--;
407  }
408 
409  /* Remove publication from node scope list, if present */
410  if (in_own_node(node)) {
411  list_del(&publ->node_list);
412  info->node_list_size--;
413  }
414 
415  /* Contract subseq list if no more publications for that subseq */
416  if (list_empty(&info->zone_list)) {
417  kfree(info);
418  free = &nseq->sseqs[nseq->first_free--];
419  memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq));
420  removed_subseq = 1;
421  }
422 
423  /* Notify any waiting subscriptions */
426  publ->lower,
427  publ->upper,
429  publ->ref,
430  publ->node,
431  removed_subseq);
432  }
433 
434  return publ;
435 }
436 
442 static void tipc_nameseq_subscribe(struct name_seq *nseq,
443  struct tipc_subscription *s)
444 {
445  struct sub_seq *sseq = nseq->sseqs;
446 
447  list_add(&s->nameseq_list, &nseq->subscriptions);
448 
449  if (!sseq)
450  return;
451 
452  while (sseq != &nseq->sseqs[nseq->first_free]) {
453  if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
454  struct publication *crs;
455  struct name_info *info = sseq->info;
456  int must_report = 1;
457 
458  list_for_each_entry(crs, &info->zone_list, zone_list) {
460  sseq->lower,
461  sseq->upper,
463  crs->ref,
464  crs->node,
465  must_report);
466  must_report = 0;
467  }
468  }
469  sseq++;
470  }
471 }
472 
473 static struct name_seq *nametbl_find_seq(u32 type)
474 {
475  struct hlist_head *seq_head;
476  struct hlist_node *seq_node;
477  struct name_seq *ns;
478 
479  seq_head = &table.types[hash(type)];
480  hlist_for_each_entry(ns, seq_node, seq_head, ns_list) {
481  if (ns->type == type)
482  return ns;
483  }
484 
485  return NULL;
486 };
487 
488 struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
489  u32 scope, u32 node, u32 port, u32 key)
490 {
491  struct name_seq *seq = nametbl_find_seq(type);
492 
493  if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE) ||
494  (lower > upper)) {
495  pr_debug("Failed to publish illegal {%u,%u,%u} with scope %u\n",
496  type, lower, upper, scope);
497  return NULL;
498  }
499 
500  if (!seq)
501  seq = tipc_nameseq_create(type, &table.types[hash(type)]);
502  if (!seq)
503  return NULL;
504 
505  return tipc_nameseq_insert_publ(seq, type, lower, upper,
506  scope, node, port, key);
507 }
508 
510  u32 node, u32 ref, u32 key)
511 {
512  struct publication *publ;
513  struct name_seq *seq = nametbl_find_seq(type);
514 
515  if (!seq)
516  return NULL;
517 
518  publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
519  nameseq_delete_empty(seq);
520  return publ;
521 }
522 
536 u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
537 {
538  struct sub_seq *sseq;
539  struct name_info *info;
540  struct publication *publ;
541  struct name_seq *seq;
542  u32 ref = 0;
543  u32 node = 0;
544 
545  if (!tipc_in_scope(*destnode, tipc_own_addr))
546  return 0;
547 
549  seq = nametbl_find_seq(type);
550  if (unlikely(!seq))
551  goto not_found;
552  sseq = nameseq_find_subseq(seq, instance);
553  if (unlikely(!sseq))
554  goto not_found;
555  spin_lock_bh(&seq->lock);
556  info = sseq->info;
557 
558  /* Closest-First Algorithm */
559  if (likely(!*destnode)) {
560  if (!list_empty(&info->node_list)) {
561  publ = list_first_entry(&info->node_list,
562  struct publication,
563  node_list);
564  list_move_tail(&publ->node_list,
565  &info->node_list);
566  } else if (!list_empty(&info->cluster_list)) {
567  publ = list_first_entry(&info->cluster_list,
568  struct publication,
569  cluster_list);
570  list_move_tail(&publ->cluster_list,
571  &info->cluster_list);
572  } else {
573  publ = list_first_entry(&info->zone_list,
574  struct publication,
575  zone_list);
576  list_move_tail(&publ->zone_list,
577  &info->zone_list);
578  }
579  }
580 
581  /* Round-Robin Algorithm */
582  else if (*destnode == tipc_own_addr) {
583  if (list_empty(&info->node_list))
584  goto no_match;
585  publ = list_first_entry(&info->node_list, struct publication,
586  node_list);
587  list_move_tail(&publ->node_list, &info->node_list);
588  } else if (in_own_cluster_exact(*destnode)) {
589  if (list_empty(&info->cluster_list))
590  goto no_match;
591  publ = list_first_entry(&info->cluster_list, struct publication,
592  cluster_list);
593  list_move_tail(&publ->cluster_list, &info->cluster_list);
594  } else {
595  publ = list_first_entry(&info->zone_list, struct publication,
596  zone_list);
597  list_move_tail(&publ->zone_list, &info->zone_list);
598  }
599 
600  ref = publ->ref;
601  node = publ->node;
602 no_match:
603  spin_unlock_bh(&seq->lock);
604 not_found:
606  *destnode = node;
607  return ref;
608 }
609 
622 int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
623  struct tipc_port_list *dports)
624 {
625  struct name_seq *seq;
626  struct sub_seq *sseq;
627  struct sub_seq *sseq_stop;
628  struct name_info *info;
629  int res = 0;
630 
632  seq = nametbl_find_seq(type);
633  if (!seq)
634  goto exit;
635 
636  spin_lock_bh(&seq->lock);
637 
638  sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
639  sseq_stop = seq->sseqs + seq->first_free;
640  for (; sseq != sseq_stop; sseq++) {
641  struct publication *publ;
642 
643  if (sseq->lower > upper)
644  break;
645 
646  info = sseq->info;
647  list_for_each_entry(publ, &info->node_list, node_list) {
648  if (publ->scope <= limit)
649  tipc_port_list_add(dports, publ->ref);
650  }
651 
652  if (info->cluster_list_size != info->node_list_size)
653  res = 1;
654  }
655 
656  spin_unlock_bh(&seq->lock);
657 exit:
659  return res;
660 }
661 
662 /*
663  * tipc_nametbl_publish - add name publication to network name tables
664  */
665 struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
666  u32 scope, u32 port_ref, u32 key)
667 {
668  struct publication *publ;
669 
670  if (table.local_publ_count >= TIPC_MAX_PUBLICATIONS) {
671  pr_warn("Publication failed, local publication limit reached (%u)\n",
673  return NULL;
674  }
675 
677  publ = tipc_nametbl_insert_publ(type, lower, upper, scope,
678  tipc_own_addr, port_ref, key);
679  if (likely(publ)) {
680  table.local_publ_count++;
681  tipc_named_publish(publ);
682  }
684  return publ;
685 }
686 
690 int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
691 {
692  struct publication *publ;
693 
695  publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
696  if (likely(publ)) {
697  table.local_publ_count--;
698  tipc_named_withdraw(publ);
700  list_del_init(&publ->pport_list);
701  kfree(publ);
702  return 1;
703  }
705  pr_err("Unable to remove local publication\n"
706  "(type=%u, lower=%u, ref=%u, key=%u)\n",
707  type, lower, ref, key);
708  return 0;
709 }
710 
715 {
716  u32 type = s->seq.type;
717  struct name_seq *seq;
718 
720  seq = nametbl_find_seq(type);
721  if (!seq)
722  seq = tipc_nameseq_create(type, &table.types[hash(type)]);
723  if (seq) {
724  spin_lock_bh(&seq->lock);
725  tipc_nameseq_subscribe(seq, s);
726  spin_unlock_bh(&seq->lock);
727  } else {
728  pr_warn("Failed to create subscription for {%u,%u,%u}\n",
729  s->seq.type, s->seq.lower, s->seq.upper);
730  }
732 }
733 
738 {
739  struct name_seq *seq;
740 
742  seq = nametbl_find_seq(s->seq.type);
743  if (seq != NULL) {
744  spin_lock_bh(&seq->lock);
745  list_del_init(&s->nameseq_list);
746  spin_unlock_bh(&seq->lock);
747  nameseq_delete_empty(seq);
748  }
750 }
751 
752 
756 static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth,
757  u32 index)
758 {
759  char portIdStr[27];
760  const char *scope_str[] = {"", " zone", " cluster", " node"};
761  struct publication *publ;
762  struct name_info *info;
763  int ret;
764 
765  ret = tipc_snprintf(buf, len, "%-10u %-10u ", sseq->lower, sseq->upper);
766 
767  if (depth == 2) {
768  ret += tipc_snprintf(buf - ret, len + ret, "\n");
769  return ret;
770  }
771 
772  info = sseq->info;
773 
774  list_for_each_entry(publ, &info->zone_list, zone_list) {
775  sprintf(portIdStr, "<%u.%u.%u:%u>",
776  tipc_zone(publ->node), tipc_cluster(publ->node),
777  tipc_node(publ->node), publ->ref);
778  ret += tipc_snprintf(buf + ret, len - ret, "%-26s ", portIdStr);
779  if (depth > 3) {
780  ret += tipc_snprintf(buf + ret, len - ret, "%-10u %s",
781  publ->key, scope_str[publ->scope]);
782  }
783  if (!list_is_last(&publ->zone_list, &info->zone_list))
784  ret += tipc_snprintf(buf + ret, len - ret,
785  "\n%33s", " ");
786  }
787 
788  ret += tipc_snprintf(buf + ret, len - ret, "\n");
789  return ret;
790 }
791 
795 static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth,
796  u32 type, u32 lowbound, u32 upbound, u32 index)
797 {
798  struct sub_seq *sseq;
799  char typearea[11];
800  int ret = 0;
801 
802  if (seq->first_free == 0)
803  return 0;
804 
805  sprintf(typearea, "%-10u", seq->type);
806 
807  if (depth == 1) {
808  ret += tipc_snprintf(buf, len, "%s\n", typearea);
809  return ret;
810  }
811 
812  for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
813  if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
814  ret += tipc_snprintf(buf + ret, len - ret, "%s ",
815  typearea);
816  spin_lock_bh(&seq->lock);
817  ret += subseq_list(sseq, buf + ret, len - ret,
818  depth, index);
819  spin_unlock_bh(&seq->lock);
820  sprintf(typearea, "%10s", " ");
821  }
822  }
823  return ret;
824 }
825 
829 static int nametbl_header(char *buf, int len, u32 depth)
830 {
831  const char *header[] = {
832  "Type ",
833  "Lower Upper ",
834  "Port Identity ",
835  "Publication Scope"
836  };
837 
838  int i;
839  int ret = 0;
840 
841  if (depth > 4)
842  depth = 4;
843  for (i = 0; i < depth; i++)
844  ret += tipc_snprintf(buf + ret, len - ret, header[i]);
845  ret += tipc_snprintf(buf + ret, len - ret, "\n");
846  return ret;
847 }
848 
852 static int nametbl_list(char *buf, int len, u32 depth_info,
853  u32 type, u32 lowbound, u32 upbound)
854 {
855  struct hlist_head *seq_head;
856  struct hlist_node *seq_node;
857  struct name_seq *seq;
858  int all_types;
859  int ret = 0;
860  u32 depth;
861  u32 i;
862 
863  all_types = (depth_info & TIPC_NTQ_ALLTYPES);
864  depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
865 
866  if (depth == 0)
867  return 0;
868 
869  if (all_types) {
870  /* display all entries in name table to specified depth */
871  ret += nametbl_header(buf, len, depth);
872  lowbound = 0;
873  upbound = ~0;
874  for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
875  seq_head = &table.types[i];
876  hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
877  ret += nameseq_list(seq, buf + ret, len - ret,
878  depth, seq->type,
879  lowbound, upbound, i);
880  }
881  }
882  } else {
883  /* display only the sequence that matches the specified type */
884  if (upbound < lowbound) {
885  ret += tipc_snprintf(buf + ret, len - ret,
886  "invalid name sequence specified\n");
887  return ret;
888  }
889  ret += nametbl_header(buf + ret, len - ret, depth);
890  i = hash(type);
891  seq_head = &table.types[i];
892  hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
893  if (seq->type == type) {
894  ret += nameseq_list(seq, buf + ret, len - ret,
895  depth, type,
896  lowbound, upbound, i);
897  break;
898  }
899  }
900  }
901  return ret;
902 }
903 
904 struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
905 {
906  struct sk_buff *buf;
907  struct tipc_name_table_query *argv;
908  struct tlv_desc *rep_tlv;
909  char *pb;
910  int pb_len;
911  int str_len;
912 
913  if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
914  return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
915 
917  if (!buf)
918  return NULL;
919 
920  rep_tlv = (struct tlv_desc *)buf->data;
921  pb = TLV_DATA(rep_tlv);
922  pb_len = ULTRA_STRING_MAX_LEN;
923  argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
925  str_len = nametbl_list(pb, pb_len, ntohl(argv->depth),
926  ntohl(argv->type),
927  ntohl(argv->lowbound), ntohl(argv->upbound));
929  str_len += 1; /* for "\0" */
930  skb_put(buf, TLV_SPACE(str_len));
931  TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
932 
933  return buf;
934 }
935 
937 {
938  table.types = kcalloc(TIPC_NAMETBL_SIZE, sizeof(struct hlist_head),
939  GFP_ATOMIC);
940  if (!table.types)
941  return -ENOMEM;
942 
943  table.local_publ_count = 0;
944  return 0;
945 }
946 
948 {
949  u32 i;
950 
951  if (!table.types)
952  return;
953 
954  /* Verify name table is empty, then release it */
956  for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
957  if (hlist_empty(&table.types[i]))
958  continue;
959  pr_err("nametbl_stop(): orphaned hash chain detected\n");
960  break;
961  }
962  kfree(table.types);
963  table.types = NULL;
965 }