Blame view

net/tipc/name_table.c 28.2 KB
b97bf3fd8   Per Liden   [TIPC] Initial merge
1
2
  /*
   * net/tipc/name_table.c: TIPC name table code
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
3
   *
593a5f22d   Per Liden   [TIPC] More updat...
4
   * Copyright (c) 2000-2006, Ericsson AB
968edbe1c   Allan Stephens   tipc: Optimizatio...
5
   * Copyright (c) 2004-2008, Wind River Systems
b97bf3fd8   Per Liden   [TIPC] Initial merge
6
7
   * All rights reserved.
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
8
   * Redistribution and use in source and binary forms, with or without
b97bf3fd8   Per Liden   [TIPC] Initial merge
9
10
   * modification, are permitted provided that the following conditions are met:
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
11
12
13
14
15
16
17
18
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the names of the copyright holders nor the names of its
   *    contributors may be used to endorse or promote products derived from
   *    this software without specific prior written permission.
b97bf3fd8   Per Liden   [TIPC] Initial merge
19
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
b97bf3fd8   Per Liden   [TIPC] Initial merge
34
35
36
37
38
39
40
41
42
43
44
45
46
47
   * POSSIBILITY OF SUCH DAMAGE.
   */
  
  #include "core.h"
  #include "config.h"
  #include "dbg.h"
  #include "name_table.h"
  #include "name_distr.h"
  #include "addr.h"
  #include "node_subscr.h"
  #include "subscr.h"
  #include "port.h"
  #include "cluster.h"
  #include "bcast.h"
988f088a8   Adrian Bunk   [TIPC]: Cleanups
48
  static int tipc_nametbl_size = 1024;		/* must be a power of 2 */
b97bf3fd8   Per Liden   [TIPC] Initial merge
49
50
51
52
53
  
  /**
   * struct sub_seq - container for all published instances of a name sequence
   * @lower: name sequence lower bound
   * @upper: name sequence upper bound
968edbe1c   Allan Stephens   tipc: Optimizatio...
54
55
56
57
58
59
60
61
62
63
   * @node_list: circular list of publications made by own node
   * @cluster_list: circular list of publications made by own cluster
   * @zone_list: circular list of publications made by own zone
   * @node_list_size: number of entries in "node_list"
   * @cluster_list_size: number of entries in "cluster_list"
   * @zone_list_size: number of entries in "zone_list"
   *
   * Note: The zone list always contains at least one entry, since all
   *       publications of the associated name sequence belong to it.
   *       (The cluster and node lists may be empty.)
b97bf3fd8   Per Liden   [TIPC] Initial merge
64
65
66
67
68
69
70
71
   */
  
  struct sub_seq {
  	u32 lower;
  	u32 upper;
  	struct publication *node_list;
  	struct publication *cluster_list;
  	struct publication *zone_list;
968edbe1c   Allan Stephens   tipc: Optimizatio...
72
73
74
  	u32 node_list_size;
  	u32 cluster_list_size;
  	u32 zone_list_size;
b97bf3fd8   Per Liden   [TIPC] Initial merge
75
  };
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
76
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
77
78
79
80
81
   * struct name_seq - container for all published instances of a name type
   * @type: 32 bit 'type' value for name sequence
   * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
   *        sub-sequences are sorted in ascending order
   * @alloc: number of sub-sequences currently in array
f131072c3   Allan Stephens   [TIPC]: First pha...
82
   * @first_free: array index of first unused sub-sequence entry
b97bf3fd8   Per Liden   [TIPC] Initial merge
83
84
   * @ns_list: links to adjacent name sequences in hash chain
   * @subscriptions: list of subscriptions for this 'type'
307fdf5e7   Allan Stephens   tipc: Add missing...
85
   * @lock: spinlock controlling access to publication lists of all sub-sequences
b97bf3fd8   Per Liden   [TIPC] Initial merge
86
87
88
89
90
91
92
93
94
95
96
97
98
99
   */
  
  struct name_seq {
  	u32 type;
  	struct sub_seq *sseqs;
  	u32 alloc;
  	u32 first_free;
  	struct hlist_node ns_list;
  	struct list_head subscriptions;
  	spinlock_t lock;
  };
  
  /**
   * struct name_table - table containing all existing port name publications
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
100
   * @types: pointer to fixed-sized array of name sequence lists,
b97bf3fd8   Per Liden   [TIPC] Initial merge
101
102
103
104
105
106
107
108
   *         accessed via hashing on 'type'; name sequence lists are *not* sorted
   * @local_publ_count: number of publications issued by this node
   */
  
  struct name_table {
  	struct hlist_head *types;
  	u32 local_publ_count;
  };
4323add67   Per Liden   [TIPC] Avoid poll...
109
  static struct name_table table = { NULL } ;
b97bf3fd8   Per Liden   [TIPC] Initial merge
110
  static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
34af946a2   Ingo Molnar   [PATCH] spin/rwlo...
111
  DEFINE_RWLOCK(tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
112

05790c645   Sam Ravnborg   [TIPC]: Remove in...
113
  static int hash(int x)
b97bf3fd8   Per Liden   [TIPC] Initial merge
114
115
116
117
118
119
120
  {
  	return(x & (tipc_nametbl_size - 1));
  }
  
  /**
   * publ_create - create a publication structure
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
121
122
  static struct publication *publ_create(u32 type, u32 lower, u32 upper,
  				       u32 scope, u32 node, u32 port_ref,
b97bf3fd8   Per Liden   [TIPC] Initial merge
123
124
  				       u32 key)
  {
0da974f4f   Panagiotis Issaris   [NET]: Conversion...
125
  	struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC);
b97bf3fd8   Per Liden   [TIPC] Initial merge
126
  	if (publ == NULL) {
a10bd924a   Allan Stephens   [TIPC]: Enhanced ...
127
128
  		warn("Publication creation failure, no memory
  ");
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
129
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
130
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  	publ->type = type;
  	publ->lower = lower;
  	publ->upper = upper;
  	publ->scope = scope;
  	publ->node = node;
  	publ->ref = port_ref;
  	publ->key = key;
  	INIT_LIST_HEAD(&publ->local_list);
  	INIT_LIST_HEAD(&publ->pport_list);
  	INIT_LIST_HEAD(&publ->subscr.nodesub_list);
  	return publ;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
145
   * tipc_subseq_alloc - allocate a specified number of sub-sequence structures
b97bf3fd8   Per Liden   [TIPC] Initial merge
146
   */
988f088a8   Adrian Bunk   [TIPC]: Cleanups
147
  static struct sub_seq *tipc_subseq_alloc(u32 cnt)
b97bf3fd8   Per Liden   [TIPC] Initial merge
148
  {
0da974f4f   Panagiotis Issaris   [NET]: Conversion...
149
  	struct sub_seq *sseq = kcalloc(cnt, sizeof(struct sub_seq), GFP_ATOMIC);
b97bf3fd8   Per Liden   [TIPC] Initial merge
150
151
152
153
  	return sseq;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
154
   * tipc_nameseq_create - create a name sequence structure for the specified 'type'
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
155
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
156
157
   * Allocates a single sub-sequence structure and sets it to all 0's.
   */
988f088a8   Adrian Bunk   [TIPC]: Cleanups
158
  static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
b97bf3fd8   Per Liden   [TIPC] Initial merge
159
  {
0da974f4f   Panagiotis Issaris   [NET]: Conversion...
160
  	struct name_seq *nseq = kzalloc(sizeof(*nseq), GFP_ATOMIC);
4323add67   Per Liden   [TIPC] Avoid poll...
161
  	struct sub_seq *sseq = tipc_subseq_alloc(1);
b97bf3fd8   Per Liden   [TIPC] Initial merge
162
163
  
  	if (!nseq || !sseq) {
a10bd924a   Allan Stephens   [TIPC]: Enhanced ...
164
165
  		warn("Name sequence creation failed, no memory
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
166
167
  		kfree(nseq);
  		kfree(sseq);
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
168
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
169
  	}
34af946a2   Ingo Molnar   [PATCH] spin/rwlo...
170
  	spin_lock_init(&nseq->lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
171
172
  	nseq->type = type;
  	nseq->sseqs = sseq;
f131072c3   Allan Stephens   [TIPC]: First pha...
173
174
  	dbg("tipc_nameseq_create(): nseq = %p, type %u, ssseqs %p, ff: %u
  ",
b97bf3fd8   Per Liden   [TIPC] Initial merge
175
176
177
178
179
180
181
182
183
184
  	    nseq, type, nseq->sseqs, nseq->first_free);
  	nseq->alloc = 1;
  	INIT_HLIST_NODE(&nseq->ns_list);
  	INIT_LIST_HEAD(&nseq->subscriptions);
  	hlist_add_head(&nseq->ns_list, seq_head);
  	return nseq;
  }
  
  /**
   * nameseq_find_subseq - find sub-sequence (if any) matching a name instance
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
185
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
186
187
   * Very time-critical, so binary searches through sub-sequence array.
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
188
189
  static struct sub_seq *nameseq_find_subseq(struct name_seq *nseq,
  					   u32 instance)
b97bf3fd8   Per Liden   [TIPC] Initial merge
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  {
  	struct sub_seq *sseqs = nseq->sseqs;
  	int low = 0;
  	int high = nseq->first_free - 1;
  	int mid;
  
  	while (low <= high) {
  		mid = (low + high) / 2;
  		if (instance < sseqs[mid].lower)
  			high = mid - 1;
  		else if (instance > sseqs[mid].upper)
  			low = mid + 1;
  		else
  			return &sseqs[mid];
  	}
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
205
  	return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
206
207
208
209
  }
  
  /**
   * nameseq_locate_subseq - determine position of name instance in sub-sequence
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
210
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
   * Returns index in sub-sequence array of the entry that contains the specified
   * instance value; if no entry contains that value, returns the position
   * where a new entry for it would be inserted in the array.
   *
   * Note: Similar to binary search code for locating a sub-sequence.
   */
  
  static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance)
  {
  	struct sub_seq *sseqs = nseq->sseqs;
  	int low = 0;
  	int high = nseq->first_free - 1;
  	int mid;
  
  	while (low <= high) {
  		mid = (low + high) / 2;
  		if (instance < sseqs[mid].lower)
  			high = mid - 1;
  		else if (instance > sseqs[mid].upper)
  			low = mid + 1;
  		else
  			return mid;
  	}
  	return low;
  }
  
  /**
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
238
   * tipc_nameseq_insert_publ -
b97bf3fd8   Per Liden   [TIPC] Initial merge
239
   */
988f088a8   Adrian Bunk   [TIPC]: Cleanups
240
241
242
  static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
  						    u32 type, u32 lower, u32 upper,
  						    u32 scope, u32 node, u32 port, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
243
244
245
246
247
248
  {
  	struct subscription *s;
  	struct subscription *st;
  	struct publication *publ;
  	struct sub_seq *sseq;
  	int created_subseq = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
249
  	sseq = nameseq_find_subseq(nseq, lower);
f131072c3   Allan Stephens   [TIPC]: First pha...
250
251
  	dbg("nameseq_ins: for seq %p, {%u,%u}, found sseq %p
  ",
b97bf3fd8   Per Liden   [TIPC] Initial merge
252
253
254
255
256
257
  	    nseq, type, lower, sseq);
  	if (sseq) {
  
  		/* Lower end overlaps existing entry => need an exact match */
  
  		if ((sseq->lower != lower) || (sseq->upper != upper)) {
f131072c3   Allan Stephens   [TIPC]: First pha...
258
259
260
  			warn("Cannot publish {%u,%u,%u}, overlap error
  ",
  			     type, lower, upper);
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
261
  			return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
262
263
264
265
266
267
268
269
270
271
272
273
274
  		}
  	} else {
  		u32 inspos;
  		struct sub_seq *freesseq;
  
  		/* Find where lower end should be inserted */
  
  		inspos = nameseq_locate_subseq(nseq, lower);
  
  		/* Fail if upper end overlaps into an existing entry */
  
  		if ((inspos < nseq->first_free) &&
  		    (upper >= nseq->sseqs[inspos].lower)) {
f131072c3   Allan Stephens   [TIPC]: First pha...
275
276
277
  			warn("Cannot publish {%u,%u,%u}, overlap error
  ",
  			     type, lower, upper);
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
278
  			return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
279
280
281
282
283
  		}
  
  		/* Ensure there is space for new sub-sequence */
  
  		if (nseq->first_free == nseq->alloc) {
9ab230f82   Allan Stephens   [TIPC]: Prevent n...
284
285
286
  			struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2);
  
  			if (!sseqs) {
f131072c3   Allan Stephens   [TIPC]: First pha...
287
288
289
  				warn("Cannot publish {%u,%u,%u}, no memory
  ",
  				     type, lower, upper);
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
290
  				return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
291
  			}
9ab230f82   Allan Stephens   [TIPC]: Prevent n...
292
293
294
295
296
297
298
  			dbg("Allocated %u more sseqs
  ", nseq->alloc);
  			memcpy(sseqs, nseq->sseqs,
  			       nseq->alloc * sizeof(struct sub_seq));
  			kfree(nseq->sseqs);
  			nseq->sseqs = sseqs;
  			nseq->alloc *= 2;
b97bf3fd8   Per Liden   [TIPC] Initial merge
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  		}
  		dbg("Have %u sseqs for type %u
  ", nseq->alloc, type);
  
  		/* Insert new sub-sequence */
  
  		dbg("ins in pos %u, ff = %u
  ", inspos, nseq->first_free);
  		sseq = &nseq->sseqs[inspos];
  		freesseq = &nseq->sseqs[nseq->first_free];
  		memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof (*sseq));
  		memset(sseq, 0, sizeof (*sseq));
  		nseq->first_free++;
  		sseq->lower = lower;
  		sseq->upper = upper;
  		created_subseq = 1;
  	}
f131072c3   Allan Stephens   [TIPC]: First pha...
316
317
  	dbg("inserting {%u,%u,%u} from <0x%x:%u> into sseq %p(%u,%u) of seq %p
  ",
b97bf3fd8   Per Liden   [TIPC] Initial merge
318
319
320
321
322
323
324
  	    type, lower, upper, node, port, sseq,
  	    sseq->lower, sseq->upper, nseq);
  
  	/* Insert a publication: */
  
  	publ = publ_create(type, lower, upper, scope, node, port, key);
  	if (!publ)
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
325
  		return NULL;
f131072c3   Allan Stephens   [TIPC]: First pha...
326
327
  	dbg("inserting publ %p, node=0x%x publ->node=0x%x, subscr->node=%p
  ",
b97bf3fd8   Per Liden   [TIPC] Initial merge
328
  	    publ, node, publ->node, publ->subscr.node);
968edbe1c   Allan Stephens   tipc: Optimizatio...
329
  	sseq->zone_list_size++;
b97bf3fd8   Per Liden   [TIPC] Initial merge
330
331
332
333
334
335
336
337
  	if (!sseq->zone_list)
  		sseq->zone_list = publ->zone_list_next = publ;
  	else {
  		publ->zone_list_next = sseq->zone_list->zone_list_next;
  		sseq->zone_list->zone_list_next = publ;
  	}
  
  	if (in_own_cluster(node)) {
968edbe1c   Allan Stephens   tipc: Optimizatio...
338
  		sseq->cluster_list_size++;
b97bf3fd8   Per Liden   [TIPC] Initial merge
339
340
341
342
343
344
345
346
347
348
  		if (!sseq->cluster_list)
  			sseq->cluster_list = publ->cluster_list_next = publ;
  		else {
  			publ->cluster_list_next =
  			sseq->cluster_list->cluster_list_next;
  			sseq->cluster_list->cluster_list_next = publ;
  		}
  	}
  
  	if (node == tipc_own_addr) {
968edbe1c   Allan Stephens   tipc: Optimizatio...
349
  		sseq->node_list_size++;
b97bf3fd8   Per Liden   [TIPC] Initial merge
350
351
352
353
354
355
356
  		if (!sseq->node_list)
  			sseq->node_list = publ->node_list_next = publ;
  		else {
  			publ->node_list_next = sseq->node_list->node_list_next;
  			sseq->node_list->node_list_next = publ;
  		}
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
357
358
  	/*
  	 * Any subscriptions waiting for notification?
b97bf3fd8   Per Liden   [TIPC] Initial merge
359
360
361
362
  	 */
  	list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
  		dbg("calling report_overlap()
  ");
4323add67   Per Liden   [TIPC] Avoid poll...
363
364
365
366
  		tipc_subscr_report_overlap(s,
  					   publ->lower,
  					   publ->upper,
  					   TIPC_PUBLISHED,
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
367
  					   publ->ref,
4323add67   Per Liden   [TIPC] Avoid poll...
368
369
  					   publ->node,
  					   created_subseq);
b97bf3fd8   Per Liden   [TIPC] Initial merge
370
371
372
373
374
  	}
  	return publ;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
375
   * tipc_nameseq_remove_publ -
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
376
   *
f131072c3   Allan Stephens   [TIPC]: First pha...
377
378
379
380
381
382
383
   * NOTE: There may be cases where TIPC is asked to remove a publication
   * that is not in the name table.  For example, if another node issues a
   * publication for a name sequence that overlaps an existing name sequence
   * the publication will not be recorded, which means the publication won't
   * be found when the name sequence is later withdrawn by that node.
   * A failed withdraw request simply returns a failure indication and lets the
   * caller issue any error or warning messages associated with such a problem.
b97bf3fd8   Per Liden   [TIPC] Initial merge
384
   */
988f088a8   Adrian Bunk   [TIPC]: Cleanups
385
386
  static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
  						    u32 node, u32 ref, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
387
388
  {
  	struct publication *publ;
f131072c3   Allan Stephens   [TIPC]: First pha...
389
  	struct publication *curr;
b97bf3fd8   Per Liden   [TIPC] Initial merge
390
391
392
393
394
  	struct publication *prev;
  	struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
  	struct sub_seq *free;
  	struct subscription *s, *st;
  	int removed_subseq = 0;
f131072c3   Allan Stephens   [TIPC]: First pha...
395
  	if (!sseq)
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
396
  		return NULL;
f131072c3   Allan Stephens   [TIPC]: First pha...
397
398
399
  
  	dbg("tipc_nameseq_remove_publ: seq: %p, sseq %p, {%u,%u}, key %u
  ",
b97bf3fd8   Per Liden   [TIPC] Initial merge
400
  	    nseq, sseq, nseq->type, inst, key);
f131072c3   Allan Stephens   [TIPC]: First pha...
401
  	/* Remove publication from zone scope list */
b97bf3fd8   Per Liden   [TIPC] Initial merge
402
403
  	prev = sseq->zone_list;
  	publ = sseq->zone_list->zone_list_next;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
404
  	while ((publ->key != key) || (publ->ref != ref) ||
b97bf3fd8   Per Liden   [TIPC] Initial merge
405
406
407
  	       (publ->node && (publ->node != node))) {
  		prev = publ;
  		publ = publ->zone_list_next;
f131072c3   Allan Stephens   [TIPC]: First pha...
408
  		if (prev == sseq->zone_list) {
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
409

f131072c3   Allan Stephens   [TIPC]: First pha...
410
411
412
413
  			/* Prevent endless loop if publication not found */
  
  			return NULL;
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
414
415
416
417
418
419
420
  	}
  	if (publ != sseq->zone_list)
  		prev->zone_list_next = publ->zone_list_next;
  	else if (publ->zone_list_next != publ) {
  		prev->zone_list_next = publ->zone_list_next;
  		sseq->zone_list = publ->zone_list_next;
  	} else {
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
421
  		sseq->zone_list = NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
422
  	}
968edbe1c   Allan Stephens   tipc: Optimizatio...
423
  	sseq->zone_list_size--;
b97bf3fd8   Per Liden   [TIPC] Initial merge
424

f131072c3   Allan Stephens   [TIPC]: First pha...
425
  	/* Remove publication from cluster scope list, if present */
b97bf3fd8   Per Liden   [TIPC] Initial merge
426
427
  	if (in_own_cluster(node)) {
  		prev = sseq->cluster_list;
f131072c3   Allan Stephens   [TIPC]: First pha...
428
429
430
431
432
433
434
435
436
437
438
439
  		curr = sseq->cluster_list->cluster_list_next;
  		while (curr != publ) {
  			prev = curr;
  			curr = curr->cluster_list_next;
  			if (prev == sseq->cluster_list) {
  
  				/* Prevent endless loop for malformed list */
  
  				err("Unable to de-list cluster publication
  "
  				    "{%u%u}, node=0x%x, ref=%u, key=%u)
  ",
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
440
  				    publ->type, publ->lower, publ->node,
f131072c3   Allan Stephens   [TIPC]: First pha...
441
442
443
  				    publ->ref, publ->key);
  				goto end_cluster;
  			}
b97bf3fd8   Per Liden   [TIPC] Initial merge
444
445
446
447
448
449
450
  		}
  		if (publ != sseq->cluster_list)
  			prev->cluster_list_next = publ->cluster_list_next;
  		else if (publ->cluster_list_next != publ) {
  			prev->cluster_list_next = publ->cluster_list_next;
  			sseq->cluster_list = publ->cluster_list_next;
  		} else {
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
451
  			sseq->cluster_list = NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
452
  		}
968edbe1c   Allan Stephens   tipc: Optimizatio...
453
  		sseq->cluster_list_size--;
b97bf3fd8   Per Liden   [TIPC] Initial merge
454
  	}
f131072c3   Allan Stephens   [TIPC]: First pha...
455
456
457
  end_cluster:
  
  	/* Remove publication from node scope list, if present */
b97bf3fd8   Per Liden   [TIPC] Initial merge
458
459
460
  
  	if (node == tipc_own_addr) {
  		prev = sseq->node_list;
f131072c3   Allan Stephens   [TIPC]: First pha...
461
462
463
464
465
466
467
468
469
470
471
472
  		curr = sseq->node_list->node_list_next;
  		while (curr != publ) {
  			prev = curr;
  			curr = curr->node_list_next;
  			if (prev == sseq->node_list) {
  
  				/* Prevent endless loop for malformed list */
  
  				err("Unable to de-list node publication
  "
  				    "{%u%u}, node=0x%x, ref=%u, key=%u)
  ",
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
473
  				    publ->type, publ->lower, publ->node,
f131072c3   Allan Stephens   [TIPC]: First pha...
474
475
476
  				    publ->ref, publ->key);
  				goto end_node;
  			}
b97bf3fd8   Per Liden   [TIPC] Initial merge
477
478
479
480
481
482
483
  		}
  		if (publ != sseq->node_list)
  			prev->node_list_next = publ->node_list_next;
  		else if (publ->node_list_next != publ) {
  			prev->node_list_next = publ->node_list_next;
  			sseq->node_list = publ->node_list_next;
  		} else {
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
484
  			sseq->node_list = NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
485
  		}
968edbe1c   Allan Stephens   tipc: Optimizatio...
486
  		sseq->node_list_size--;
b97bf3fd8   Per Liden   [TIPC] Initial merge
487
  	}
f131072c3   Allan Stephens   [TIPC]: First pha...
488
  end_node:
b97bf3fd8   Per Liden   [TIPC] Initial merge
489

f131072c3   Allan Stephens   [TIPC]: First pha...
490
491
492
  	/* Contract subseq list if no more publications for that subseq */
  
  	if (!sseq->zone_list) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
493
494
495
496
  		free = &nseq->sseqs[nseq->first_free--];
  		memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq));
  		removed_subseq = 1;
  	}
f131072c3   Allan Stephens   [TIPC]: First pha...
497
  	/* Notify any waiting subscriptions */
b97bf3fd8   Per Liden   [TIPC] Initial merge
498
  	list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
4323add67   Per Liden   [TIPC] Avoid poll...
499
500
501
  		tipc_subscr_report_overlap(s,
  					   publ->lower,
  					   publ->upper,
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
502
503
  					   TIPC_WITHDRAWN,
  					   publ->ref,
4323add67   Per Liden   [TIPC] Avoid poll...
504
505
  					   publ->node,
  					   removed_subseq);
b97bf3fd8   Per Liden   [TIPC] Initial merge
506
  	}
f131072c3   Allan Stephens   [TIPC]: First pha...
507

b97bf3fd8   Per Liden   [TIPC] Initial merge
508
509
510
511
  	return publ;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
512
   * tipc_nameseq_subscribe: attach a subscription, and issue
b97bf3fd8   Per Liden   [TIPC] Initial merge
513
514
515
   * the prescribed number of events if there is any sub-
   * sequence overlapping with the requested sequence
   */
248bbf382   Florian Westphal   [TIPC]: Make func...
516
  static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s)
b97bf3fd8   Per Liden   [TIPC] Initial merge
517
518
519
520
521
522
523
524
525
526
  {
  	struct sub_seq *sseq = nseq->sseqs;
  
  	list_add(&s->nameseq_list, &nseq->subscriptions);
  
  	if (!sseq)
  		return;
  
  	while (sseq != &nseq->sseqs[nseq->first_free]) {
  		struct publication *zl = sseq->zone_list;
4323add67   Per Liden   [TIPC] Avoid poll...
527
  		if (zl && tipc_subscr_overlap(s,sseq->lower,sseq->upper)) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
528
529
530
531
  			struct publication *crs = zl;
  			int must_report = 1;
  
  			do {
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
532
533
  				tipc_subscr_report_overlap(s,
  							   sseq->lower,
4323add67   Per Liden   [TIPC] Avoid poll...
534
535
536
537
538
  							   sseq->upper,
  							   TIPC_PUBLISHED,
  							   crs->ref,
  							   crs->node,
  							   must_report);
b97bf3fd8   Per Liden   [TIPC] Initial merge
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  				must_report = 0;
  				crs = crs->zone_list_next;
  			} while (crs != zl);
  		}
  		sseq++;
  	}
  }
  
  static struct name_seq *nametbl_find_seq(u32 type)
  {
  	struct hlist_head *seq_head;
  	struct hlist_node *seq_node;
  	struct name_seq *ns;
  
  	dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u
  ",
f574179b6   Harvey Harrison   tipc: trivial end...
555
  	    type, htonl(type), type, table.types, hash(type));
b97bf3fd8   Per Liden   [TIPC] Initial merge
556
557
558
559
  
  	seq_head = &table.types[hash(type)];
  	hlist_for_each_entry(ns, seq_node, seq_head, ns_list) {
  		if (ns->type == type) {
f131072c3   Allan Stephens   [TIPC]: First pha...
560
561
  			dbg("found %p
  ", ns);
b97bf3fd8   Per Liden   [TIPC] Initial merge
562
563
564
  			return ns;
  		}
  	}
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
565
  	return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
566
  };
4323add67   Per Liden   [TIPC] Avoid poll...
567
568
  struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
  					     u32 scope, u32 node, u32 port, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
569
570
  {
  	struct name_seq *seq = nametbl_find_seq(type);
f131072c3   Allan Stephens   [TIPC]: First pha...
571
572
  	dbg("tipc_nametbl_insert_publ: {%u,%u,%u} found %p
  ", type, lower, upper, seq);
b97bf3fd8   Per Liden   [TIPC] Initial merge
573
  	if (lower > upper) {
f131072c3   Allan Stephens   [TIPC]: First pha...
574
575
  		warn("Failed to publish illegal {%u,%u,%u}
  ",
b97bf3fd8   Per Liden   [TIPC] Initial merge
576
  		     type, lower, upper);
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
577
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
578
  	}
f131072c3   Allan Stephens   [TIPC]: First pha...
579
580
  	dbg("Publishing {%u,%u,%u} from 0x%x
  ", type, lower, upper, node);
b97bf3fd8   Per Liden   [TIPC] Initial merge
581
  	if (!seq) {
4323add67   Per Liden   [TIPC] Avoid poll...
582
  		seq = tipc_nameseq_create(type, &table.types[hash(type)]);
f131072c3   Allan Stephens   [TIPC]: First pha...
583
584
  		dbg("tipc_nametbl_insert_publ: created %p
  ", seq);
b97bf3fd8   Per Liden   [TIPC] Initial merge
585
586
  	}
  	if (!seq)
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
587
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
588

4323add67   Per Liden   [TIPC] Avoid poll...
589
590
  	return tipc_nameseq_insert_publ(seq, type, lower, upper,
  					scope, node, port, key);
b97bf3fd8   Per Liden   [TIPC] Initial merge
591
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
592
  struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
4323add67   Per Liden   [TIPC] Avoid poll...
593
  					     u32 node, u32 ref, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
594
595
596
597
598
  {
  	struct publication *publ;
  	struct name_seq *seq = nametbl_find_seq(type);
  
  	if (!seq)
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
599
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
600

f131072c3   Allan Stephens   [TIPC]: First pha...
601
602
  	dbg("Withdrawing {%u,%u} from 0x%x
  ", type, lower, node);
4323add67   Per Liden   [TIPC] Avoid poll...
603
  	publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
b97bf3fd8   Per Liden   [TIPC] Initial merge
604
605
606
607
608
609
610
611
612
613
  
  	if (!seq->first_free && list_empty(&seq->subscriptions)) {
  		hlist_del_init(&seq->ns_list);
  		kfree(seq->sseqs);
  		kfree(seq);
  	}
  	return publ;
  }
  
  /*
4323add67   Per Liden   [TIPC] Avoid poll...
614
   * tipc_nametbl_translate(): Translate tipc_name -> tipc_portid.
b97bf3fd8   Per Liden   [TIPC] Initial merge
615
616
617
618
619
   *                      Very time-critical.
   *
   * Note: on entry 'destnode' is the search domain used during translation;
   *       on exit it passes back the node address of the matching port (if any)
   */
4323add67   Per Liden   [TIPC] Avoid poll...
620
  u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
b97bf3fd8   Per Liden   [TIPC] Initial merge
621
622
  {
  	struct sub_seq *sseq;
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
623
  	struct publication *publ = NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
624
625
626
627
628
  	struct name_seq *seq;
  	u32 ref;
  
  	if (!in_scope(*destnode, tipc_own_addr))
  		return 0;
4323add67   Per Liden   [TIPC] Avoid poll...
629
  	read_lock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
  	seq = nametbl_find_seq(type);
  	if (unlikely(!seq))
  		goto not_found;
  	sseq = nameseq_find_subseq(seq, instance);
  	if (unlikely(!sseq))
  		goto not_found;
  	spin_lock_bh(&seq->lock);
  
  	/* Closest-First Algorithm: */
  	if (likely(!*destnode)) {
  		publ = sseq->node_list;
  		if (publ) {
  			sseq->node_list = publ->node_list_next;
  found:
  			ref = publ->ref;
  			*destnode = publ->node;
  			spin_unlock_bh(&seq->lock);
4323add67   Per Liden   [TIPC] Avoid poll...
647
  			read_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
  			return ref;
  		}
  		publ = sseq->cluster_list;
  		if (publ) {
  			sseq->cluster_list = publ->cluster_list_next;
  			goto found;
  		}
  		publ = sseq->zone_list;
  		if (publ) {
  			sseq->zone_list = publ->zone_list_next;
  			goto found;
  		}
  	}
  
  	/* Round-Robin Algorithm: */
  	else if (*destnode == tipc_own_addr) {
  		publ = sseq->node_list;
  		if (publ) {
  			sseq->node_list = publ->node_list_next;
  			goto found;
  		}
  	} else if (in_own_cluster(*destnode)) {
  		publ = sseq->cluster_list;
  		if (publ) {
  			sseq->cluster_list = publ->cluster_list_next;
  			goto found;
  		}
  	} else {
  		publ = sseq->zone_list;
  		if (publ) {
  			sseq->zone_list = publ->zone_list_next;
  			goto found;
  		}
  	}
  	spin_unlock_bh(&seq->lock);
  not_found:
  	*destnode = 0;
4323add67   Per Liden   [TIPC] Avoid poll...
685
  	read_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
686
687
688
689
  	return 0;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
690
   * tipc_nametbl_mc_translate - find multicast destinations
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
691
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
692
693
694
695
696
697
   * Creates list of all local ports that overlap the given multicast address;
   * also determines if any off-node ports overlap.
   *
   * Note: Publications with a scope narrower than 'limit' are ignored.
   * (i.e. local node-scope publications mustn't receive messages arriving
   * from another node, even if the multcast link brought it here)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
698
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
699
700
   * Returns non-zero if any off-node ports overlap
   */
4323add67   Per Liden   [TIPC] Avoid poll...
701
702
  int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
  			      struct port_list *dports)
b97bf3fd8   Per Liden   [TIPC] Initial merge
703
704
705
706
707
  {
  	struct name_seq *seq;
  	struct sub_seq *sseq;
  	struct sub_seq *sseq_stop;
  	int res = 0;
4323add67   Per Liden   [TIPC] Avoid poll...
708
  	read_lock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
709
710
711
712
713
714
715
716
717
718
719
720
721
  	seq = nametbl_find_seq(type);
  	if (!seq)
  		goto exit;
  
  	spin_lock_bh(&seq->lock);
  
  	sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
  	sseq_stop = seq->sseqs + seq->first_free;
  	for (; sseq != sseq_stop; sseq++) {
  		struct publication *publ;
  
  		if (sseq->lower > upper)
  			break;
968edbe1c   Allan Stephens   tipc: Optimizatio...
722
723
724
  
  		publ = sseq->node_list;
  		if (publ) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
725
  			do {
968edbe1c   Allan Stephens   tipc: Optimizatio...
726
  				if (publ->scope <= limit)
4323add67   Per Liden   [TIPC] Avoid poll...
727
  					tipc_port_list_add(dports, publ->ref);
968edbe1c   Allan Stephens   tipc: Optimizatio...
728
729
730
731
732
733
  				publ = publ->node_list_next;
  			} while (publ != sseq->node_list);
  		}
  
  		if (sseq->cluster_list_size != sseq->node_list_size)
  			res = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
734
735
736
737
  	}
  
  	spin_unlock_bh(&seq->lock);
  exit:
4323add67   Per Liden   [TIPC] Avoid poll...
738
  	read_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
739
740
741
742
  	return res;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
743
   * tipc_nametbl_publish_rsv - publish port name using a reserved name type
b97bf3fd8   Per Liden   [TIPC] Initial merge
744
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
745
  int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope,
b97bf3fd8   Per Liden   [TIPC] Initial merge
746
747
748
749
750
751
752
753
754
755
756
  			struct tipc_name_seq const *seq)
  {
  	int res;
  
  	atomic_inc(&rsv_publ_ok);
  	res = tipc_publish(ref, scope, seq);
  	atomic_dec(&rsv_publ_ok);
  	return res;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
757
   * tipc_nametbl_publish - add name publication to network name tables
b97bf3fd8   Per Liden   [TIPC] Initial merge
758
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
759
  struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
b97bf3fd8   Per Liden   [TIPC] Initial merge
760
761
762
763
764
  				    u32 scope, u32 port_ref, u32 key)
  {
  	struct publication *publ;
  
  	if (table.local_publ_count >= tipc_max_publications) {
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
765
766
  		warn("Publication failed, local publication limit reached (%u)
  ",
b97bf3fd8   Per Liden   [TIPC] Initial merge
767
  		     tipc_max_publications);
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
768
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
769
770
  	}
  	if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) {
f131072c3   Allan Stephens   [TIPC]: First pha...
771
772
  		warn("Publication failed, reserved name {%u,%u,%u}
  ",
b97bf3fd8   Per Liden   [TIPC] Initial merge
773
  		     type, lower, upper);
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
774
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
775
  	}
4323add67   Per Liden   [TIPC] Avoid poll...
776
  	write_lock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
777
  	table.local_publ_count++;
4323add67   Per Liden   [TIPC] Avoid poll...
778
  	publ = tipc_nametbl_insert_publ(type, lower, upper, scope,
b97bf3fd8   Per Liden   [TIPC] Initial merge
779
780
  				   tipc_own_addr, port_ref, key);
  	if (publ && (scope != TIPC_NODE_SCOPE)) {
4323add67   Per Liden   [TIPC] Avoid poll...
781
  		tipc_named_publish(publ);
b97bf3fd8   Per Liden   [TIPC] Initial merge
782
  	}
4323add67   Per Liden   [TIPC] Avoid poll...
783
  	write_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
784
785
786
787
  	return publ;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
788
   * tipc_nametbl_withdraw - withdraw name publication from network name tables
b97bf3fd8   Per Liden   [TIPC] Initial merge
789
   */
4323add67   Per Liden   [TIPC] Avoid poll...
790
  int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
791
792
  {
  	struct publication *publ;
f131072c3   Allan Stephens   [TIPC]: First pha...
793
794
  	dbg("tipc_nametbl_withdraw: {%u,%u}, key=%u
  ", type, lower, key);
4323add67   Per Liden   [TIPC] Avoid poll...
795
796
  	write_lock_bh(&tipc_nametbl_lock);
  	publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
f131072c3   Allan Stephens   [TIPC]: First pha...
797
  	if (likely(publ)) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
798
799
  		table.local_publ_count--;
  		if (publ->scope != TIPC_NODE_SCOPE)
4323add67   Per Liden   [TIPC] Avoid poll...
800
801
  			tipc_named_withdraw(publ);
  		write_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
802
803
804
805
  		list_del_init(&publ->pport_list);
  		kfree(publ);
  		return 1;
  	}
4323add67   Per Liden   [TIPC] Avoid poll...
806
  	write_unlock_bh(&tipc_nametbl_lock);
f131072c3   Allan Stephens   [TIPC]: First pha...
807
808
809
810
811
  	err("Unable to remove local publication
  "
  	    "(type=%u, lower=%u, ref=%u, key=%u)
  ",
  	    type, lower, ref, key);
b97bf3fd8   Per Liden   [TIPC] Initial merge
812
813
814
815
  	return 0;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
816
   * tipc_nametbl_subscribe - add a subscription object to the name table
b97bf3fd8   Per Liden   [TIPC] Initial merge
817
   */
f131072c3   Allan Stephens   [TIPC]: First pha...
818
  void tipc_nametbl_subscribe(struct subscription *s)
b97bf3fd8   Per Liden   [TIPC] Initial merge
819
820
821
  {
  	u32 type = s->seq.type;
  	struct name_seq *seq;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
822
  	write_lock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
823
824
  	seq = nametbl_find_seq(type);
  	if (!seq) {
4323add67   Per Liden   [TIPC] Avoid poll...
825
  		seq = tipc_nameseq_create(type, &table.types[hash(type)]);
b97bf3fd8   Per Liden   [TIPC] Initial merge
826
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
827
828
829
830
831
832
833
834
  	if (seq){
  		spin_lock_bh(&seq->lock);
  		dbg("tipc_nametbl_subscribe:found %p for {%u,%u,%u}
  ",
  		    seq, type, s->seq.lower, s->seq.upper);
  		tipc_nameseq_subscribe(seq, s);
  		spin_unlock_bh(&seq->lock);
  	} else {
f131072c3   Allan Stephens   [TIPC]: First pha...
835
836
837
  		warn("Failed to create subscription for {%u,%u,%u}
  ",
  		     s->seq.type, s->seq.lower, s->seq.upper);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
838
839
  	}
  	write_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
840
841
842
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
843
   * tipc_nametbl_unsubscribe - remove a subscription object from name table
b97bf3fd8   Per Liden   [TIPC] Initial merge
844
   */
f131072c3   Allan Stephens   [TIPC]: First pha...
845
  void tipc_nametbl_unsubscribe(struct subscription *s)
b97bf3fd8   Per Liden   [TIPC] Initial merge
846
847
  {
  	struct name_seq *seq;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
848
849
  	write_lock_bh(&tipc_nametbl_lock);
  	seq = nametbl_find_seq(s->seq.type);
b97bf3fd8   Per Liden   [TIPC] Initial merge
850
  	if (seq != NULL){
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
851
852
853
854
855
856
857
858
859
860
  		spin_lock_bh(&seq->lock);
  		list_del_init(&s->nameseq_list);
  		spin_unlock_bh(&seq->lock);
  		if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) {
  			hlist_del_init(&seq->ns_list);
  			kfree(seq->sseqs);
  			kfree(seq);
  		}
  	}
  	write_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
  }
  
  
  /**
   * subseq_list: print specified sub-sequence contents into the given buffer
   */
  
  static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
  			u32 index)
  {
  	char portIdStr[27];
  	char *scopeStr;
  	struct publication *publ = sseq->zone_list;
  
  	tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
  
  	if (depth == 2 || !publ) {
  		tipc_printf(buf, "
  ");
  		return;
  	}
  
  	do {
  		sprintf (portIdStr, "<%u.%u.%u:%u>",
  			 tipc_zone(publ->node), tipc_cluster(publ->node),
  			 tipc_node(publ->node), publ->ref);
  		tipc_printf(buf, "%-26s ", portIdStr);
  		if (depth > 3) {
  			if (publ->node != tipc_own_addr)
  				scopeStr = "";
  			else if (publ->scope == TIPC_NODE_SCOPE)
  				scopeStr = "node";
  			else if (publ->scope == TIPC_CLUSTER_SCOPE)
  				scopeStr = "cluster";
  			else
  				scopeStr = "zone";
  			tipc_printf(buf, "%-10u %s", publ->key, scopeStr);
  		}
  
  		publ = publ->zone_list_next;
  		if (publ == sseq->zone_list)
  			break;
  
  		tipc_printf(buf, "
  %33s", " ");
  	} while (1);
  
  	tipc_printf(buf, "
  ");
  }
  
  /**
   * nameseq_list: print specified name sequence contents into the given buffer
   */
  
  static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth,
  			 u32 type, u32 lowbound, u32 upbound, u32 index)
  {
  	struct sub_seq *sseq;
  	char typearea[11];
0f15d3645   Allan Stephens   tipc: Prevent dis...
921
922
  	if (seq->first_free == 0)
  		return;
b97bf3fd8   Per Liden   [TIPC] Initial merge
923
924
925
926
927
928
929
930
931
932
933
  	sprintf(typearea, "%-10u", seq->type);
  
  	if (depth == 1) {
  		tipc_printf(buf, "%s
  ", typearea);
  		return;
  	}
  
  	for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
  		if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
  			tipc_printf(buf, "%s ", typearea);
307fdf5e7   Allan Stephens   tipc: Add missing...
934
  			spin_lock_bh(&seq->lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
935
  			subseq_list(sseq, buf, depth, index);
307fdf5e7   Allan Stephens   tipc: Add missing...
936
  			spin_unlock_bh(&seq->lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
  			sprintf(typearea, "%10s", " ");
  		}
  	}
  }
  
  /**
   * nametbl_header - print name table header into the given buffer
   */
  
  static void nametbl_header(struct print_buf *buf, u32 depth)
  {
  	tipc_printf(buf, "Type       ");
  
  	if (depth > 1)
  		tipc_printf(buf, "Lower      Upper      ");
  	if (depth > 2)
  		tipc_printf(buf, "Port Identity              ");
  	if (depth > 3)
  		tipc_printf(buf, "Publication");
  
  	tipc_printf(buf, "
  -----------");
  
  	if (depth > 1)
  		tipc_printf(buf, "--------------------- ");
  	if (depth > 2)
  		tipc_printf(buf, "-------------------------- ");
  	if (depth > 3)
  		tipc_printf(buf, "------------------");
  
  	tipc_printf(buf, "
  ");
  }
  
  /**
   * nametbl_list - print specified name table contents into the given buffer
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
974
  static void nametbl_list(struct print_buf *buf, u32 depth_info,
b97bf3fd8   Per Liden   [TIPC] Initial merge
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
  			 u32 type, u32 lowbound, u32 upbound)
  {
  	struct hlist_head *seq_head;
  	struct hlist_node *seq_node;
  	struct name_seq *seq;
  	int all_types;
  	u32 depth;
  	u32 i;
  
  	all_types = (depth_info & TIPC_NTQ_ALLTYPES);
  	depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
  
  	if (depth == 0)
  		return;
  
  	if (all_types) {
  		/* display all entries in name table to specified depth */
  		nametbl_header(buf, depth);
  		lowbound = 0;
  		upbound = ~0;
  		for (i = 0; i < tipc_nametbl_size; i++) {
  			seq_head = &table.types[i];
  			hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
998
  				nameseq_list(seq, buf, depth, seq->type,
b97bf3fd8   Per Liden   [TIPC] Initial merge
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
  					     lowbound, upbound, i);
  			}
  		}
  	} else {
  		/* display only the sequence that matches the specified type */
  		if (upbound < lowbound) {
  			tipc_printf(buf, "invalid name sequence specified
  ");
  			return;
  		}
  		nametbl_header(buf, depth);
  		i = hash(type);
  		seq_head = &table.types[i];
  		hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
  			if (seq->type == type) {
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1014
  				nameseq_list(seq, buf, depth, type,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1015
1016
1017
1018
1019
1020
  					     lowbound, upbound, i);
  				break;
  			}
  		}
  	}
  }
988f088a8   Adrian Bunk   [TIPC]: Cleanups
1021
  #if 0
4323add67   Per Liden   [TIPC] Avoid poll...
1022
  void tipc_nametbl_print(struct print_buf *buf, const char *str)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1023
1024
  {
  	tipc_printf(buf, str);
4323add67   Per Liden   [TIPC] Avoid poll...
1025
  	read_lock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1026
  	nametbl_list(buf, 0, 0, 0, 0);
4323add67   Per Liden   [TIPC] Avoid poll...
1027
  	read_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1028
  }
988f088a8   Adrian Bunk   [TIPC]: Cleanups
1029
  #endif
b97bf3fd8   Per Liden   [TIPC] Initial merge
1030
1031
  
  #define MAX_NAME_TBL_QUERY 32768
4323add67   Per Liden   [TIPC] Avoid poll...
1032
  struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1033
1034
1035
1036
1037
1038
1039
1040
  {
  	struct sk_buff *buf;
  	struct tipc_name_table_query *argv;
  	struct tlv_desc *rep_tlv;
  	struct print_buf b;
  	int str_len;
  
  	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
4323add67   Per Liden   [TIPC] Avoid poll...
1041
  		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1042

4323add67   Per Liden   [TIPC] Avoid poll...
1043
  	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY));
b97bf3fd8   Per Liden   [TIPC] Initial merge
1044
1045
1046
1047
  	if (!buf)
  		return NULL;
  
  	rep_tlv = (struct tlv_desc *)buf->data;
4323add67   Per Liden   [TIPC] Avoid poll...
1048
  	tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1049
  	argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
4323add67   Per Liden   [TIPC] Avoid poll...
1050
  	read_lock_bh(&tipc_nametbl_lock);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1051
  	nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type),
b97bf3fd8   Per Liden   [TIPC] Initial merge
1052
  		     ntohl(argv->lowbound), ntohl(argv->upbound));
4323add67   Per Liden   [TIPC] Avoid poll...
1053
1054
  	read_unlock_bh(&tipc_nametbl_lock);
  	str_len = tipc_printbuf_validate(&b);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1055
1056
1057
1058
1059
1060
  
  	skb_put(buf, TLV_SPACE(str_len));
  	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
  
  	return buf;
  }
988f088a8   Adrian Bunk   [TIPC]: Cleanups
1061
  #if 0
4323add67   Per Liden   [TIPC] Avoid poll...
1062
  void tipc_nametbl_dump(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1063
  {
4323add67   Per Liden   [TIPC] Avoid poll...
1064
  	nametbl_list(TIPC_CONS, 0, 0, 0, 0);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1065
  }
988f088a8   Adrian Bunk   [TIPC]: Cleanups
1066
  #endif
b97bf3fd8   Per Liden   [TIPC] Initial merge
1067

4323add67   Per Liden   [TIPC] Avoid poll...
1068
  int tipc_nametbl_init(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1069
  {
4e3e6dcb4   Allan Stephens   tipc: Enhancement...
1070
1071
  	table.types = kcalloc(tipc_nametbl_size, sizeof(struct hlist_head),
  			      GFP_ATOMIC);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1072
1073
  	if (!table.types)
  		return -ENOMEM;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1074
  	table.local_publ_count = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1075
1076
  	return 0;
  }
4323add67   Per Liden   [TIPC] Avoid poll...
1077
  void tipc_nametbl_stop(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1078
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
1079
1080
1081
1082
  	u32 i;
  
  	if (!table.types)
  		return;
f131072c3   Allan Stephens   [TIPC]: First pha...
1083
  	/* Verify name table is empty, then release it */
4323add67   Per Liden   [TIPC] Avoid poll...
1084
  	write_lock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1085
  	for (i = 0; i < tipc_nametbl_size; i++) {
f131072c3   Allan Stephens   [TIPC]: First pha...
1086
1087
1088
  		if (!hlist_empty(&table.types[i]))
  			err("tipc_nametbl_stop(): hash chain %u is non-null
  ", i);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1089
1090
1091
  	}
  	kfree(table.types);
  	table.types = NULL;
4323add67   Per Liden   [TIPC] Avoid poll...
1092
  	write_unlock_bh(&tipc_nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1093
  }
f131072c3   Allan Stephens   [TIPC]: First pha...
1094