aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2014-08-22 18:09:19 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-23 14:18:35 -0400
commit808d90f9c55943c2965d33b7156e559c59dd2db9 (patch)
treea0f507b1cb62b8fde785b30486eff6b3127038f9 /net/tipc/socket.c
parent2e84c60b77e4dd96068f568a5971e681bb7e6b68 (diff)
tipc: remove files ref.h and ref.c
The reference table is now 'socket aware' instead of being generic, and has in reality become a socket internal table. In order to be able to minimize the API exposed by the socket layer towards the rest of the stack, we now move the reference table definitions and functions into the file socket.c, and rename the functions accordingly. There are no functional changes in this commit. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c247
1 files changed, 244 insertions, 3 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 70eaceae1f8c..6a699671245b 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -35,7 +35,6 @@
35 */ 35 */
36 36
37#include "core.h" 37#include "core.h"
38#include "ref.h"
39#include "name_table.h" 38#include "name_table.h"
40#include "node.h" 39#include "node.h"
41#include "link.h" 40#include "link.h"
@@ -61,6 +60,11 @@ static int tipc_sk_publish(struct tipc_port *port, uint scope,
61 struct tipc_name_seq const *seq); 60 struct tipc_name_seq const *seq);
62static int tipc_sk_withdraw(struct tipc_port *port, uint scope, 61static int tipc_sk_withdraw(struct tipc_port *port, uint scope,
63 struct tipc_name_seq const *seq); 62 struct tipc_name_seq const *seq);
63static u32 tipc_sk_ref_acquire(struct tipc_sock *tsk);
64static void tipc_sk_ref_discard(u32 ref);
65static struct tipc_sock *tipc_sk_get(u32 ref);
66static struct tipc_sock *tipc_sk_get_next(u32 *ref);
67static void tipc_sk_put(struct tipc_sock *tsk);
64 68
65static const struct proto_ops packet_ops; 69static const struct proto_ops packet_ops;
66static const struct proto_ops stream_ops; 70static const struct proto_ops stream_ops;
@@ -271,7 +275,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
271 275
272 tsk = tipc_sk(sk); 276 tsk = tipc_sk(sk);
273 port = &tsk->port; 277 port = &tsk->port;
274 ref = tipc_ref_acquire(tsk); 278 ref = tipc_sk_ref_acquire(tsk);
275 if (!ref) { 279 if (!ref) {
276 pr_warn("Socket create failed; reference table exhausted\n"); 280 pr_warn("Socket create failed; reference table exhausted\n");
277 return -ENOMEM; 281 return -ENOMEM;
@@ -434,7 +438,7 @@ static int tipc_release(struct socket *sock)
434 } 438 }
435 439
436 tipc_sk_withdraw(port, 0, NULL); 440 tipc_sk_withdraw(port, 0, NULL);
437 tipc_ref_discard(port->ref); 441 tipc_sk_ref_discard(port->ref);
438 k_cancel_timer(&port->timer); 442 k_cancel_timer(&port->timer);
439 if (port->connected) { 443 if (port->connected) {
440 buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, 444 buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
@@ -2254,6 +2258,243 @@ void tipc_sk_reinit(void)
2254} 2258}
2255 2259
2256/** 2260/**
2261 * struct reference - TIPC socket reference entry
2262 * @tsk: pointer to socket associated with reference entry
2263 * @ref: reference value for socket (combines instance & array index info)
2264 */
2265struct reference {
2266 struct tipc_sock *tsk;
2267 u32 ref;
2268};
2269
2270/**
2271 * struct tipc_ref_table - table of TIPC socket reference entries
2272 * @entries: pointer to array of reference entries
2273 * @capacity: array index of first unusable entry
2274 * @init_point: array index of first uninitialized entry
2275 * @first_free: array index of first unused socket reference entry
2276 * @last_free: array index of last unused socket reference entry
2277 * @index_mask: bitmask for array index portion of reference values
2278 * @start_mask: initial value for instance value portion of reference values
2279 */
2280struct ref_table {
2281 struct reference *entries;
2282 u32 capacity;
2283 u32 init_point;
2284 u32 first_free;
2285 u32 last_free;
2286 u32 index_mask;
2287 u32 start_mask;
2288};
2289
2290/* Socket reference table consists of 2**N entries.
2291 *
2292 * State Socket ptr Reference
2293 * ----- ---------- ---------
2294 * In use non-NULL XXXX|own index
2295 * (XXXX changes each time entry is acquired)
2296 * Free NULL YYYY|next free index
2297 * (YYYY is one more than last used XXXX)
2298 * Uninitialized NULL 0
2299 *
2300 * Entry 0 is not used; this allows index 0 to denote the end of the free list.
2301 *
2302 * Note that a reference value of 0 does not necessarily indicate that an
2303 * entry is uninitialized, since the last entry in the free list could also
2304 * have a reference value of 0 (although this is unlikely).
2305 */
2306
2307static struct ref_table tipc_ref_table;
2308
2309static DEFINE_RWLOCK(ref_table_lock);
2310
2311/**
2312 * tipc_ref_table_init - create reference table for sockets
2313 */
2314int tipc_sk_ref_table_init(u32 req_sz, u32 start)
2315{
2316 struct reference *table;
2317 u32 actual_sz;
2318
2319 /* account for unused entry, then round up size to a power of 2 */
2320
2321 req_sz++;
2322 for (actual_sz = 16; actual_sz < req_sz; actual_sz <<= 1) {
2323 /* do nothing */
2324 };
2325
2326 /* allocate table & mark all entries as uninitialized */
2327 table = vzalloc(actual_sz * sizeof(struct reference));
2328 if (table == NULL)
2329 return -ENOMEM;
2330
2331 tipc_ref_table.entries = table;
2332 tipc_ref_table.capacity = req_sz;
2333 tipc_ref_table.init_point = 1;
2334 tipc_ref_table.first_free = 0;
2335 tipc_ref_table.last_free = 0;
2336 tipc_ref_table.index_mask = actual_sz - 1;
2337 tipc_ref_table.start_mask = start & ~tipc_ref_table.index_mask;
2338
2339 return 0;
2340}
2341
2342/**
2343 * tipc_ref_table_stop - destroy reference table for sockets
2344 */
2345void tipc_sk_ref_table_stop(void)
2346{
2347 if (!tipc_ref_table.entries)
2348 return;
2349 vfree(tipc_ref_table.entries);
2350 tipc_ref_table.entries = NULL;
2351}
2352
2353/* tipc_ref_acquire - create reference to a socket
2354 *
2355 * Register an socket pointer in the reference table.
2356 * Returns a unique reference value that is used from then on to retrieve the
2357 * socket pointer, or to determine if the socket has been deregistered.
2358 */
2359u32 tipc_sk_ref_acquire(struct tipc_sock *tsk)
2360{
2361 u32 index;
2362 u32 index_mask;
2363 u32 next_plus_upper;
2364 u32 ref = 0;
2365 struct reference *entry;
2366
2367 if (unlikely(!tsk)) {
2368 pr_err("Attempt to acquire ref. to non-existent obj\n");
2369 return 0;
2370 }
2371 if (unlikely(!tipc_ref_table.entries)) {
2372 pr_err("Ref. table not found in acquisition attempt\n");
2373 return 0;
2374 }
2375
2376 /* Take a free entry, if available; otherwise initialize a new one */
2377 write_lock_bh(&ref_table_lock);
2378 index = tipc_ref_table.first_free;
2379 entry = &tipc_ref_table.entries[index];
2380
2381 if (likely(index)) {
2382 index = tipc_ref_table.first_free;
2383 entry = &tipc_ref_table.entries[index];
2384 index_mask = tipc_ref_table.index_mask;
2385 next_plus_upper = entry->ref;
2386 tipc_ref_table.first_free = next_plus_upper & index_mask;
2387 ref = (next_plus_upper & ~index_mask) + index;
2388 entry->tsk = tsk;
2389 } else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {
2390 index = tipc_ref_table.init_point++;
2391 entry = &tipc_ref_table.entries[index];
2392 ref = tipc_ref_table.start_mask + index;
2393 }
2394
2395 if (ref) {
2396 entry->ref = ref;
2397 entry->tsk = tsk;
2398 }
2399 write_unlock_bh(&ref_table_lock);
2400 return ref;
2401}
2402
2403/* tipc_sk_ref_discard - invalidate reference to an socket
2404 *
2405 * Disallow future references to an socket and free up the entry for re-use.
2406 */
2407void tipc_sk_ref_discard(u32 ref)
2408{
2409 struct reference *entry;
2410 u32 index;
2411 u32 index_mask;
2412
2413 if (unlikely(!tipc_ref_table.entries)) {
2414 pr_err("Ref. table not found during discard attempt\n");
2415 return;
2416 }
2417
2418 index_mask = tipc_ref_table.index_mask;
2419 index = ref & index_mask;
2420 entry = &tipc_ref_table.entries[index];
2421
2422 write_lock_bh(&ref_table_lock);
2423
2424 if (unlikely(!entry->tsk)) {
2425 pr_err("Attempt to discard ref. to non-existent socket\n");
2426 goto exit;
2427 }
2428 if (unlikely(entry->ref != ref)) {
2429 pr_err("Attempt to discard non-existent reference\n");
2430 goto exit;
2431 }
2432
2433 /* Mark entry as unused; increment instance part of entry's
2434 * reference to invalidate any subsequent references
2435 */
2436
2437 entry->tsk = NULL;
2438 entry->ref = (ref & ~index_mask) + (index_mask + 1);
2439
2440 /* Append entry to free entry list */
2441 if (unlikely(tipc_ref_table.first_free == 0))
2442 tipc_ref_table.first_free = index;
2443 else
2444 tipc_ref_table.entries[tipc_ref_table.last_free].ref |= index;
2445 tipc_ref_table.last_free = index;
2446exit:
2447 write_unlock_bh(&ref_table_lock);
2448}
2449
2450/* tipc_sk_get - find referenced socket and return pointer to it
2451 */
2452struct tipc_sock *tipc_sk_get(u32 ref)
2453{
2454 struct reference *entry;
2455 struct tipc_sock *tsk;
2456
2457 if (unlikely(!tipc_ref_table.entries))
2458 return NULL;
2459 read_lock_bh(&ref_table_lock);
2460 entry = &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
2461 tsk = entry->tsk;
2462 if (likely(tsk && (entry->ref == ref)))
2463 sock_hold(&tsk->sk);
2464 else
2465 tsk = NULL;
2466 read_unlock_bh(&ref_table_lock);
2467 return tsk;
2468}
2469
2470/* tipc_sk_get_next - lock & return next socket after referenced one
2471*/
2472struct tipc_sock *tipc_sk_get_next(u32 *ref)
2473{
2474 struct reference *entry;
2475 struct tipc_sock *tsk = NULL;
2476 uint index = *ref & tipc_ref_table.index_mask;
2477
2478 read_lock_bh(&ref_table_lock);
2479 while (++index < tipc_ref_table.capacity) {
2480 entry = &tipc_ref_table.entries[index];
2481 if (!entry->tsk)
2482 continue;
2483 tsk = entry->tsk;
2484 sock_hold(&tsk->sk);
2485 *ref = entry->ref;
2486 break;
2487 }
2488 read_unlock_bh(&ref_table_lock);
2489 return tsk;
2490}
2491
2492static void tipc_sk_put(struct tipc_sock *tsk)
2493{
2494 sock_put(&tsk->sk);
2495}
2496
2497/**
2257 * tipc_setsockopt - set socket option 2498 * tipc_setsockopt - set socket option
2258 * @sock: socket structure 2499 * @sock: socket structure
2259 * @lvl: option level 2500 * @lvl: option level