2006-01-02 21:04:38 +03:00
/*
2008-05-20 00:30:13 +04:00
* net / tipc / subscr . c : TIPC network topology service
2007-02-09 17:25:21 +03:00
*
2006-01-11 21:14:19 +03:00
* Copyright ( c ) 2000 - 2006 , Ericsson AB
2008-05-20 00:30:13 +04:00
* Copyright ( c ) 2005 - 2007 , Wind River Systems
2006-01-02 21:04:38 +03:00
* All rights reserved .
*
2006-01-11 15:30:43 +03:00
* Redistribution and use in source and binary forms , with or without
2006-01-02 21:04:38 +03:00
* modification , are permitted provided that the following conditions are met :
*
2006-01-11 15:30:43 +03:00
* 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 .
2006-01-02 21:04:38 +03:00
*
2006-01-11 15:30:43 +03:00
* 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
2006-01-02 21:04:38 +03:00
* POSSIBILITY OF SUCH DAMAGE .
*/
# include "core.h"
# include "dbg.h"
# include "name_table.h"
2008-05-20 00:29:47 +04:00
# include "port.h"
2006-01-02 21:04:38 +03:00
# include "ref.h"
2008-05-20 00:30:13 +04:00
# include "subscr.h"
2006-01-02 21:04:38 +03:00
/**
* struct subscriber - TIPC network topology subscriber
2008-05-20 00:29:47 +04:00
* @ port_ref : object reference to server port connecting to subscriber
* @ lock : pointer to spinlock controlling access to subscriber ' s server port
2006-01-02 21:04:38 +03:00
* @ subscriber_list : adjacent subscribers in top . server ' s list of subscribers
* @ subscription_list : list of subscription objects for this subscriber
*/
2007-02-09 17:25:21 +03:00
2006-01-02 21:04:38 +03:00
struct subscriber {
2008-05-20 00:29:47 +04:00
u32 port_ref ;
2007-02-09 17:25:21 +03:00
spinlock_t * lock ;
2006-01-02 21:04:38 +03:00
struct list_head subscriber_list ;
struct list_head subscription_list ;
} ;
/**
* struct top_srv - TIPC network topology subscription service
* @ user_ref : TIPC userid of subscription service
* @ setup_port : reference to TIPC port that handles subscription requests
* @ subscription_count : number of active subscriptions ( not subscribers ! )
* @ subscriber_list : list of ports subscribing to service
* @ lock : spinlock govering access to subscriber list
*/
struct top_srv {
u32 user_ref ;
u32 setup_port ;
atomic_t subscription_count ;
struct list_head subscriber_list ;
spinlock_t lock ;
} ;
static struct top_srv topsrv = { 0 } ;
/**
* htohl - convert value to endianness used by destination
* @ in : value to convert
* @ swap : non - zero if endianness must be reversed
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* Returns converted value
*/
2006-03-21 09:37:04 +03:00
static u32 htohl ( u32 in , int swap )
2006-01-02 21:04:38 +03:00
{
2008-08-13 13:32:06 +04:00
return swap ? swab32 ( in ) : in ;
2006-01-02 21:04:38 +03:00
}
/**
* subscr_send_event - send a message containing a tipc_event to the subscriber
2008-05-20 00:29:47 +04:00
*
* Note : Must not hold subscriber ' s server port lock , since tipc_send ( ) will
* try to take the lock if the message is rejected and returned !
2006-01-02 21:04:38 +03:00
*/
2007-02-09 17:25:21 +03:00
static void subscr_send_event ( struct subscription * sub ,
u32 found_lower ,
2006-01-02 21:04:38 +03:00
u32 found_upper ,
2007-02-09 17:25:21 +03:00
u32 event ,
u32 port_ref ,
2006-01-02 21:04:38 +03:00
u32 node )
{
struct iovec msg_sect ;
msg_sect . iov_base = ( void * ) & sub - > evt ;
msg_sect . iov_len = sizeof ( struct tipc_event ) ;
2008-05-20 00:28:32 +04:00
sub - > evt . event = htohl ( event , sub - > swap ) ;
sub - > evt . found_lower = htohl ( found_lower , sub - > swap ) ;
sub - > evt . found_upper = htohl ( found_upper , sub - > swap ) ;
sub - > evt . port . ref = htohl ( port_ref , sub - > swap ) ;
sub - > evt . port . node = htohl ( node , sub - > swap ) ;
2008-05-20 00:29:47 +04:00
tipc_send ( sub - > server_ref , 1 , & msg_sect ) ;
2006-01-02 21:04:38 +03:00
}
/**
2006-01-18 02:38:21 +03:00
* tipc_subscr_overlap - test for subscription overlap with the given values
2006-01-02 21:04:38 +03:00
*
* Returns 1 if there is overlap , otherwise 0.
*/
2007-02-09 17:25:21 +03:00
int tipc_subscr_overlap ( struct subscription * sub ,
u32 found_lower ,
2006-01-18 02:38:21 +03:00
u32 found_upper )
2006-01-02 21:04:38 +03:00
{
if ( found_lower < sub - > seq . lower )
found_lower = sub - > seq . lower ;
if ( found_upper > sub - > seq . upper )
found_upper = sub - > seq . upper ;
if ( found_lower > found_upper )
return 0 ;
return 1 ;
}
/**
2006-01-18 02:38:21 +03:00
* tipc_subscr_report_overlap - issue event if there is subscription overlap
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* Protected by nameseq . lock in name_table . c
*/
2007-02-09 17:25:21 +03:00
void tipc_subscr_report_overlap ( struct subscription * sub ,
u32 found_lower ,
2006-01-18 02:38:21 +03:00
u32 found_upper ,
2007-02-09 17:25:21 +03:00
u32 event ,
u32 port_ref ,
2006-01-18 02:38:21 +03:00
u32 node ,
int must )
2006-01-02 21:04:38 +03:00
{
2006-01-18 02:38:21 +03:00
if ( ! tipc_subscr_overlap ( sub , found_lower , found_upper ) )
2006-01-02 21:04:38 +03:00
return ;
2006-10-17 08:59:42 +04:00
if ( ! must & & ! ( sub - > filter & TIPC_SUB_PORTS ) )
2006-01-02 21:04:38 +03:00
return ;
2008-05-20 00:27:31 +04:00
sub - > event_cb ( sub , found_lower , found_upper , event , port_ref , node ) ;
2006-01-02 21:04:38 +03:00
}
/**
* subscr_timeout - subscription timeout has occurred
*/
static void subscr_timeout ( struct subscription * sub )
{
2008-05-20 00:29:47 +04:00
struct port * server_port ;
2006-01-02 21:04:38 +03:00
2008-05-20 00:29:47 +04:00
/* Validate server port reference (in case subscriber is terminating) */
2006-01-02 21:04:38 +03:00
2008-05-20 00:29:47 +04:00
server_port = tipc_port_lock ( sub - > server_ref ) ;
if ( server_port = = NULL )
2006-01-02 21:04:38 +03:00
return ;
2006-10-17 08:59:42 +04:00
/* Validate timeout (in case subscription is being cancelled) */
if ( sub - > timeout = = TIPC_WAIT_FOREVER ) {
2008-05-20 00:29:47 +04:00
tipc_port_unlock ( server_port ) ;
2006-10-17 08:59:42 +04:00
return ;
}
2006-01-02 21:04:38 +03:00
/* Unlink subscription from name table */
2006-01-18 02:38:21 +03:00
tipc_nametbl_unsubscribe ( sub ) ;
2006-01-02 21:04:38 +03:00
2008-05-20 00:29:47 +04:00
/* Unlink subscription from subscriber */
2006-01-02 21:04:38 +03:00
list_del ( & sub - > subscription_list ) ;
2008-05-20 00:29:47 +04:00
/* Release subscriber's server port */
tipc_port_unlock ( server_port ) ;
/* Notify subscriber of timeout */
subscr_send_event ( sub , sub - > evt . s . seq . lower , sub - > evt . s . seq . upper ,
TIPC_SUBSCR_TIMEOUT , 0 , 0 ) ;
2006-01-02 21:04:38 +03:00
/* Now destroy subscription */
k_term_timer ( & sub - > timer ) ;
kfree ( sub ) ;
atomic_dec ( & topsrv . subscription_count ) ;
}
2006-10-17 08:59:42 +04:00
/**
* subscr_del - delete a subscription within a subscription list
*
2008-05-20 00:29:47 +04:00
* Called with subscriber port locked .
2006-10-17 08:59:42 +04:00
*/
static void subscr_del ( struct subscription * sub )
{
tipc_nametbl_unsubscribe ( sub ) ;
list_del ( & sub - > subscription_list ) ;
kfree ( sub ) ;
atomic_dec ( & topsrv . subscription_count ) ;
}
2006-01-02 21:04:38 +03:00
/**
* subscr_terminate - terminate communication with a subscriber
2007-02-09 17:25:21 +03:00
*
2008-05-20 00:29:47 +04:00
* Called with subscriber port locked . Routine must temporarily release lock
2007-02-09 17:25:21 +03:00
* to enable subscription timeout routine ( s ) to finish without deadlocking ;
2006-01-02 21:04:38 +03:00
* the lock is then reclaimed to allow caller to release it upon return .
2007-02-09 17:25:21 +03:00
* ( This should work even in the unlikely event some other thread creates
2006-01-02 21:04:38 +03:00
* a new object reference in the interim that uses this lock ; this routine will
* simply wait for it to be released , then claim it . )
*/
static void subscr_terminate ( struct subscriber * subscriber )
{
2008-05-20 00:29:47 +04:00
u32 port_ref ;
2006-01-02 21:04:38 +03:00
struct subscription * sub ;
struct subscription * sub_temp ;
/* Invalidate subscriber reference */
2008-05-20 00:29:47 +04:00
port_ref = subscriber - > port_ref ;
subscriber - > port_ref = 0 ;
2006-01-02 21:04:38 +03:00
spin_unlock_bh ( subscriber - > lock ) ;
2008-05-20 00:29:47 +04:00
/* Sever connection to subscriber */
tipc_shutdown ( port_ref ) ;
tipc_deleteport ( port_ref ) ;
2006-01-02 21:04:38 +03:00
/* Destroy any existing subscriptions for subscriber */
2007-02-09 17:25:21 +03:00
2006-01-02 21:04:38 +03:00
list_for_each_entry_safe ( sub , sub_temp , & subscriber - > subscription_list ,
subscription_list ) {
if ( sub - > timeout ! = TIPC_WAIT_FOREVER ) {
k_cancel_timer ( & sub - > timer ) ;
k_term_timer ( & sub - > timer ) ;
}
2006-10-17 08:59:42 +04:00
dbg ( " Term: Removing sub %u,%u,%u from subscriber %x list \n " ,
2006-01-02 21:04:38 +03:00
sub - > seq . type , sub - > seq . lower , sub - > seq . upper , subscriber ) ;
2006-10-17 08:59:42 +04:00
subscr_del ( sub ) ;
2006-01-02 21:04:38 +03:00
}
/* Remove subscriber from topology server's subscriber list */
spin_lock_bh ( & topsrv . lock ) ;
list_del ( & subscriber - > subscriber_list ) ;
spin_unlock_bh ( & topsrv . lock ) ;
2008-05-20 00:29:47 +04:00
/* Reclaim subscriber lock */
2006-01-02 21:04:38 +03:00
spin_lock_bh ( subscriber - > lock ) ;
2008-05-20 00:29:47 +04:00
/* Now destroy subscriber */
2006-01-02 21:04:38 +03:00
kfree ( subscriber ) ;
}
2006-10-17 08:59:42 +04:00
/**
* subscr_cancel - handle subscription cancellation request
*
2008-05-20 00:29:47 +04:00
* Called with subscriber port locked . Routine must temporarily release lock
2006-10-17 08:59:42 +04:00
* to enable the subscription timeout routine to finish without deadlocking ;
* the lock is then reclaimed to allow caller to release it upon return .
*
* Note that fields of ' s ' use subscriber ' s endianness !
*/
static void subscr_cancel ( struct tipc_subscr * s ,
struct subscriber * subscriber )
{
struct subscription * sub ;
struct subscription * sub_temp ;
int found = 0 ;
/* Find first matching subscription, exit if not found */
list_for_each_entry_safe ( sub , sub_temp , & subscriber - > subscription_list ,
subscription_list ) {
if ( ! memcmp ( s , & sub - > evt . s , sizeof ( struct tipc_subscr ) ) ) {
found = 1 ;
break ;
}
}
if ( ! found )
return ;
/* Cancel subscription timer (if used), then delete subscription */
if ( sub - > timeout ! = TIPC_WAIT_FOREVER ) {
sub - > timeout = TIPC_WAIT_FOREVER ;
spin_unlock_bh ( subscriber - > lock ) ;
k_cancel_timer ( & sub - > timer ) ;
k_term_timer ( & sub - > timer ) ;
spin_lock_bh ( subscriber - > lock ) ;
}
dbg ( " Cancel: removing sub %u,%u,%u from subscriber %x list \n " ,
sub - > seq . type , sub - > seq . lower , sub - > seq . upper , subscriber ) ;
subscr_del ( sub ) ;
}
2006-01-02 21:04:38 +03:00
/**
* subscr_subscribe - create subscription for subscriber
2007-02-09 17:25:21 +03:00
*
2008-05-20 00:29:47 +04:00
* Called with subscriber port locked .
2006-01-02 21:04:38 +03:00
*/
2008-05-20 00:29:47 +04:00
static struct subscription * subscr_subscribe ( struct tipc_subscr * s ,
struct subscriber * subscriber )
2006-01-02 21:04:38 +03:00
{
struct subscription * sub ;
2008-05-20 00:28:32 +04:00
int swap ;
2006-01-02 21:04:38 +03:00
2008-05-20 00:28:32 +04:00
/* Determine subscriber's endianness */
2006-10-17 08:59:42 +04:00
2008-05-20 00:28:32 +04:00
swap = ! ( s - > filter & ( TIPC_SUB_PORTS | TIPC_SUB_SERVICE ) ) ;
2006-10-17 08:59:42 +04:00
/* Detect & process a subscription cancellation request */
2008-05-20 00:28:32 +04:00
if ( s - > filter & htohl ( TIPC_SUB_CANCEL , swap ) ) {
s - > filter & = ~ htohl ( TIPC_SUB_CANCEL , swap ) ;
2006-10-17 08:59:42 +04:00
subscr_cancel ( s , subscriber ) ;
2008-05-20 00:29:47 +04:00
return NULL ;
2006-10-17 08:59:42 +04:00
}
2006-01-02 21:04:38 +03:00
/* Refuse subscription if global limit exceeded */
if ( atomic_read ( & topsrv . subscription_count ) > = tipc_max_subscriptions ) {
2006-06-26 10:52:17 +04:00
warn ( " Subscription rejected, subscription limit reached (%u) \n " ,
tipc_max_subscriptions ) ;
2006-01-02 21:04:38 +03:00
subscr_terminate ( subscriber ) ;
2008-05-20 00:29:47 +04:00
return NULL ;
2006-01-02 21:04:38 +03:00
}
/* Allocate subscription object */
2008-05-20 00:29:47 +04:00
sub = kmalloc ( sizeof ( * sub ) , GFP_ATOMIC ) ;
2006-06-26 10:52:17 +04:00
if ( ! sub ) {
warn ( " Subscription rejected, no memory \n " ) ;
2006-01-02 21:04:38 +03:00
subscr_terminate ( subscriber ) ;
2008-05-20 00:29:47 +04:00
return NULL ;
2006-01-02 21:04:38 +03:00
}
/* Initialize subscription object */
2008-05-20 00:28:32 +04:00
sub - > seq . type = htohl ( s - > seq . type , swap ) ;
sub - > seq . lower = htohl ( s - > seq . lower , swap ) ;
sub - > seq . upper = htohl ( s - > seq . upper , swap ) ;
sub - > timeout = htohl ( s - > timeout , swap ) ;
sub - > filter = htohl ( s - > filter , swap ) ;
2009-11-30 03:55:45 +03:00
if ( ( ! ( sub - > filter & TIPC_SUB_PORTS ) = =
! ( sub - > filter & TIPC_SUB_SERVICE ) ) | |
( sub - > seq . lower > sub - > seq . upper ) ) {
2006-06-26 10:52:17 +04:00
warn ( " Subscription rejected, illegal request \n " ) ;
2006-01-02 21:04:38 +03:00
kfree ( sub ) ;
subscr_terminate ( subscriber ) ;
2008-05-20 00:29:47 +04:00
return NULL ;
2006-01-02 21:04:38 +03:00
}
2008-05-20 00:27:31 +04:00
sub - > event_cb = subscr_send_event ;
2006-01-02 21:04:38 +03:00
INIT_LIST_HEAD ( & sub - > nameseq_list ) ;
list_add ( & sub - > subscription_list , & subscriber - > subscription_list ) ;
2008-05-20 00:29:47 +04:00
sub - > server_ref = subscriber - > port_ref ;
2008-05-20 00:28:32 +04:00
sub - > swap = swap ;
2008-05-20 00:29:47 +04:00
memcpy ( & sub - > evt . s , s , sizeof ( struct tipc_subscr ) ) ;
2006-01-02 21:04:38 +03:00
atomic_inc ( & topsrv . subscription_count ) ;
if ( sub - > timeout ! = TIPC_WAIT_FOREVER ) {
k_init_timer ( & sub - > timer ,
( Handler ) subscr_timeout , ( unsigned long ) sub ) ;
k_start_timer ( & sub - > timer , sub - > timeout ) ;
}
2008-05-20 00:29:47 +04:00
return sub ;
2006-01-02 21:04:38 +03:00
}
/**
* subscr_conn_shutdown_event - handle termination request from subscriber
2008-05-20 00:29:47 +04:00
*
* Called with subscriber ' s server port unlocked .
2006-01-02 21:04:38 +03:00
*/
static void subscr_conn_shutdown_event ( void * usr_handle ,
2008-05-20 00:29:47 +04:00
u32 port_ref ,
2006-01-02 21:04:38 +03:00
struct sk_buff * * buf ,
unsigned char const * data ,
unsigned int size ,
int reason )
{
2008-05-20 00:29:47 +04:00
struct subscriber * subscriber = usr_handle ;
2006-01-02 21:04:38 +03:00
spinlock_t * subscriber_lock ;
2008-05-20 00:29:47 +04:00
if ( tipc_port_lock ( port_ref ) = = NULL )
2006-01-02 21:04:38 +03:00
return ;
subscriber_lock = subscriber - > lock ;
subscr_terminate ( subscriber ) ;
spin_unlock_bh ( subscriber_lock ) ;
}
/**
* subscr_conn_msg_event - handle new subscription request from subscriber
2008-05-20 00:29:47 +04:00
*
* Called with subscriber ' s server port unlocked .
2006-01-02 21:04:38 +03:00
*/
static void subscr_conn_msg_event ( void * usr_handle ,
u32 port_ref ,
struct sk_buff * * buf ,
const unchar * data ,
u32 size )
{
2008-05-20 00:29:47 +04:00
struct subscriber * subscriber = usr_handle ;
2006-01-02 21:04:38 +03:00
spinlock_t * subscriber_lock ;
2008-05-20 00:29:47 +04:00
struct subscription * sub ;
/*
* Lock subscriber ' s server port ( & make a local copy of lock pointer ,
* in case subscriber is deleted while processing subscription request )
*/
2006-01-02 21:04:38 +03:00
2008-05-20 00:29:47 +04:00
if ( tipc_port_lock ( port_ref ) = = NULL )
2006-01-02 21:04:38 +03:00
return ;
subscriber_lock = subscriber - > lock ;
2007-02-09 17:25:21 +03:00
2008-05-20 00:29:47 +04:00
if ( size ! = sizeof ( struct tipc_subscr ) ) {
subscr_terminate ( subscriber ) ;
spin_unlock_bh ( subscriber_lock ) ;
} else {
sub = subscr_subscribe ( ( struct tipc_subscr * ) data , subscriber ) ;
spin_unlock_bh ( subscriber_lock ) ;
if ( sub ! = NULL ) {
/*
* We must release the server port lock before adding a
* subscription to the name table since TIPC needs to be
* able to ( re ) acquire the port lock if an event message
* issued by the subscription process is rejected and
* returned . The subscription cannot be deleted while
* it is being added to the name table because :
* a ) the single - threading of the native API port code
* ensures the subscription cannot be cancelled and
* the subscriber connection cannot be broken , and
* b ) the name table lock ensures the subscription
* timeout code cannot delete the subscription ,
* so the subscription object is still protected .
*/
tipc_nametbl_subscribe ( sub ) ;
}
}
2006-01-02 21:04:38 +03:00
}
/**
* subscr_named_msg_event - handle request to establish a new subscriber
*/
static void subscr_named_msg_event ( void * usr_handle ,
u32 port_ref ,
struct sk_buff * * buf ,
const unchar * data ,
u32 size ,
2007-02-09 17:25:21 +03:00
u32 importance ,
2006-01-02 21:04:38 +03:00
struct tipc_portid const * orig ,
struct tipc_name_seq const * dest )
{
2008-05-20 00:29:47 +04:00
static struct iovec msg_sect = { NULL , 0 } ;
2006-01-02 21:04:38 +03:00
2008-05-20 00:29:47 +04:00
struct subscriber * subscriber ;
u32 server_port_ref ;
2006-01-02 21:04:38 +03:00
/* Create subscriber object */
2006-07-22 01:51:30 +04:00
subscriber = kzalloc ( sizeof ( struct subscriber ) , GFP_ATOMIC ) ;
2006-01-02 21:04:38 +03:00
if ( subscriber = = NULL ) {
2006-06-26 10:52:17 +04:00
warn ( " Subscriber rejected, no memory \n " ) ;
2006-01-02 21:04:38 +03:00
return ;
}
INIT_LIST_HEAD ( & subscriber - > subscription_list ) ;
INIT_LIST_HEAD ( & subscriber - > subscriber_list ) ;
2008-05-20 00:29:47 +04:00
/* Create server port & establish connection to subscriber */
2006-01-02 21:04:38 +03:00
tipc_createport ( topsrv . user_ref ,
2008-05-20 00:29:47 +04:00
subscriber ,
2006-01-02 21:04:38 +03:00
importance ,
2006-03-21 09:36:47 +03:00
NULL ,
NULL ,
2006-01-02 21:04:38 +03:00
subscr_conn_shutdown_event ,
2006-03-21 09:36:47 +03:00
NULL ,
NULL ,
2006-01-02 21:04:38 +03:00
subscr_conn_msg_event ,
2006-03-21 09:36:47 +03:00
NULL ,
2006-01-02 21:04:38 +03:00
& subscriber - > port_ref ) ;
if ( subscriber - > port_ref = = 0 ) {
2006-06-26 10:52:17 +04:00
warn ( " Subscriber rejected, unable to create port \n " ) ;
2006-01-02 21:04:38 +03:00
kfree ( subscriber ) ;
return ;
}
tipc_connect2port ( subscriber - > port_ref , orig ) ;
2008-05-20 00:29:47 +04:00
/* Lock server port (& save lock address for future use) */
subscriber - > lock = tipc_port_lock ( subscriber - > port_ref ) - > publ . lock ;
2006-01-02 21:04:38 +03:00
/* Add subscriber to topology server's subscriber list */
spin_lock_bh ( & topsrv . lock ) ;
list_add ( & subscriber - > subscriber_list , & topsrv . subscriber_list ) ;
spin_unlock_bh ( & topsrv . lock ) ;
2008-05-20 00:29:47 +04:00
/* Unlock server port */
2006-01-02 21:04:38 +03:00
2008-05-20 00:29:47 +04:00
server_port_ref = subscriber - > port_ref ;
spin_unlock_bh ( subscriber - > lock ) ;
2006-01-02 21:04:38 +03:00
2008-05-20 00:29:47 +04:00
/* Send an ACK- to complete connection handshaking */
tipc_send ( server_port_ref , 1 , & msg_sect ) ;
/* Handle optional subscription request */
if ( size ! = 0 ) {
subscr_conn_msg_event ( subscriber , server_port_ref ,
buf , data , size ) ;
}
2006-01-02 21:04:38 +03:00
}
2006-01-18 02:38:21 +03:00
int tipc_subscr_start ( void )
2006-01-02 21:04:38 +03:00
{
struct tipc_name_seq seq = { TIPC_TOP_SRV , TIPC_TOP_SRV , TIPC_TOP_SRV } ;
int res = - 1 ;
memset ( & topsrv , 0 , sizeof ( topsrv ) ) ;
2006-06-27 13:53:55 +04:00
spin_lock_init ( & topsrv . lock ) ;
2006-01-02 21:04:38 +03:00
INIT_LIST_HEAD ( & topsrv . subscriber_list ) ;
spin_lock_bh ( & topsrv . lock ) ;
2006-03-21 09:36:47 +03:00
res = tipc_attach ( & topsrv . user_ref , NULL , NULL ) ;
2006-01-02 21:04:38 +03:00
if ( res ) {
spin_unlock_bh ( & topsrv . lock ) ;
return res ;
}
2007-02-09 17:25:21 +03:00
res = tipc_createport ( topsrv . user_ref ,
NULL ,
TIPC_CRITICAL_IMPORTANCE ,
NULL ,
NULL ,
NULL ,
NULL ,
subscr_named_msg_event ,
NULL ,
NULL ,
& topsrv . setup_port ) ;
if ( res )
2006-01-02 21:04:38 +03:00
goto failed ;
2007-02-09 17:25:21 +03:00
res = tipc_nametbl_publish_rsv ( topsrv . setup_port , TIPC_NODE_SCOPE , & seq ) ;
if ( res )
2006-01-02 21:04:38 +03:00
goto failed ;
spin_unlock_bh ( & topsrv . lock ) ;
return 0 ;
failed :
2006-01-11 15:52:51 +03:00
err ( " Failed to create subscription service \n " ) ;
2006-01-02 21:04:38 +03:00
tipc_detach ( topsrv . user_ref ) ;
topsrv . user_ref = 0 ;
spin_unlock_bh ( & topsrv . lock ) ;
return res ;
}
2006-01-18 02:38:21 +03:00
void tipc_subscr_stop ( void )
2006-01-02 21:04:38 +03:00
{
struct subscriber * subscriber ;
struct subscriber * subscriber_temp ;
spinlock_t * subscriber_lock ;
if ( topsrv . user_ref ) {
tipc_deleteport ( topsrv . setup_port ) ;
2007-02-09 17:25:21 +03:00
list_for_each_entry_safe ( subscriber , subscriber_temp ,
2006-01-02 21:04:38 +03:00
& topsrv . subscriber_list ,
subscriber_list ) {
subscriber_lock = subscriber - > lock ;
2008-05-20 00:29:47 +04:00
spin_lock_bh ( subscriber_lock ) ;
2006-01-02 21:04:38 +03:00
subscr_terminate ( subscriber ) ;
spin_unlock_bh ( subscriber_lock ) ;
}
tipc_detach ( topsrv . user_ref ) ;
topsrv . user_ref = 0 ;
}
}
int tipc_ispublished ( struct tipc_name const * name )
{
u32 domain = 0 ;
2006-01-18 02:38:21 +03:00
return ( tipc_nametbl_translate ( name - > type , name - > instance , & domain ) ! = 0 ) ;
2006-01-02 21:04:38 +03:00
}