From: ftillier Date: Wed, 6 Jul 2005 18:59:19 +0000 (+0000) Subject: Changed how SA requests are handled from user-mode. Synchronous requests X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=4c9becbd6d127fdfa92b85770d1d8ecb85d4dc9b;p=~shefty%2Frdma-win.git Changed how SA requests are handled from user-mode. Synchronous requests now use synchronous IOCTL processing rather than blocking in user-mode and waiting for the IOCTL completion callback. This eliminates the potential for deadlocks resulting from clients making synchronous SA queries from a callback thread context. git-svn-id: svn://openib.tc.cornell.edu/gen1@23 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- diff --git a/branches/fab_cm_branch/core/al/al_mcast.c b/branches/fab_cm_branch/core/al/al_mcast.c index 0111a237..14cb159b 100644 --- a/branches/fab_cm_branch/core/al/al_mcast.c +++ b/branches/fab_cm_branch/core/al/al_mcast.c @@ -264,7 +264,7 @@ __destroying_mcast( ref_al_obj( &h_mcast->obj ); status = al_send_sa_req( - &h_mcast->sa_dereg_req, h_mcast->port_guid, 500, 0, &sa_mad_data ); + &h_mcast->sa_dereg_req, h_mcast->port_guid, 500, 0, &sa_mad_data, 0 ); if( status != IB_SUCCESS ) deref_al_obj( &h_mcast->obj ); @@ -395,7 +395,7 @@ send_join( p_mcast->state = SA_REG_STARTING; status = al_send_sa_req( &p_mcast->sa_reg_req, p_mcast->port_guid, - p_mcast_req->timeout_ms, p_mcast_req->retry_cnt, &sa_mad_data ); + p_mcast_req->timeout_ms, p_mcast_req->retry_cnt, &sa_mad_data, 0 ); CL_EXIT( AL_DBG_MCAST, g_al_dbg_lvl ); return status; diff --git a/branches/fab_cm_branch/core/al/al_query.c b/branches/fab_cm_branch/core/al/al_query.c index 00c6c6f4..f6fd620d 100644 --- a/branches/fab_cm_branch/core/al/al_query.c +++ b/branches/fab_cm_branch/core/al/al_query.c @@ -48,18 +48,14 @@ static ib_api_status_t query_sa( IN al_query_t *p_query, - IN const ib_query_req_t* const p_query_req ); + IN const ib_query_req_t* const p_query_req, + IN const ib_al_flags_t flags ); void query_req_cb( IN al_sa_req_t *p_sa_req, IN ib_mad_element_t *p_mad_response ); -static void -__free_query( - IN OUT al_query_t *p_query ); - - ib_api_status_t ib_query( @@ -69,8 +65,6 @@ ib_query( { al_query_t *p_query; ib_api_status_t status; - cl_status_t cl_status; - boolean_t sync; CL_ENTER( AL_DBG_QUERY, g_al_dbg_lvl ); @@ -98,23 +92,6 @@ ib_query( return IB_INSUFFICIENT_MEMORY; } - /* Check for synchronous operation. */ - p_query->flags = p_query_req->flags; - cl_event_construct( &p_query->event ); - sync = ( (p_query->flags & IB_FLAGS_SYNC) == IB_FLAGS_SYNC ); - if( sync ) - { - cl_status = cl_event_init( &p_query->event, TRUE ); - if( cl_status != CL_SUCCESS ) - { - status = ib_convert_cl_status( cl_status ); - CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, - ("cl_init_event failed: %s\n", ib_get_err_str(status) ) ); - __free_query( p_query ); - return status; - } - } - /* Copy the query context information. */ p_query->sa_req.pfn_sa_req_cb = query_req_cb; p_query->sa_req.user_context = p_query_req->query_context; @@ -124,38 +101,26 @@ ib_query( /* Track the query with the AL instance. */ al_insert_query( h_al, p_query ); + /* + * Set the query handle now so that users that do sync queries + * can also cancel the queries. + */ + if( ph_query ) + *ph_query = p_query; + /* Issue the MAD to the SA. */ - status = query_sa( p_query, (ib_query_req_t*)p_query_req ); - if( status == IB_SUCCESS ) - { - /* - * Set the query handle now so that users that do sync queries - * can also cancel the queries. - */ - if( ph_query ) - *ph_query = p_query; - /* If synchronous, wait for the completion. */ - if( sync ) - { - do - { - cl_status = cl_event_wait_on( - &p_query->event, EVENT_NO_TIMEOUT, AL_WAIT_ALERTABLE ); - } while( cl_status == CL_NOT_DONE ); - CL_ASSERT( cl_status == CL_SUCCESS ); - } - } - else if( status != IB_INVALID_GUID ) + status = query_sa( p_query, p_query_req, p_query_req->flags ); + if( status != IB_SUCCESS && status != IB_INVALID_GUID ) { CL_TRACE( AL_DBG_ERROR, g_al_dbg_lvl, ("query_sa failed: %s\n", ib_get_err_str(status) ) ); } /* Cleanup from issuing the query if it failed or was synchronous. */ - if( ( status != IB_SUCCESS ) || sync ) + if( status != IB_SUCCESS ) { al_remove_query( p_query ); - __free_query( p_query ); + cl_free( p_query ); } CL_EXIT( AL_DBG_QUERY, g_al_dbg_lvl ); @@ -170,7 +135,8 @@ ib_query( static ib_api_status_t query_sa( IN al_query_t *p_query, - IN const ib_query_req_t* const p_query_req ) + IN const ib_query_req_t* const p_query_req, + IN const ib_al_flags_t flags ) { ib_user_query_t sa_req, *p_sa_req; union _query_sa_recs @@ -329,7 +295,7 @@ query_sa( status = al_send_sa_req( &p_query->sa_req, p_query_req->port_guid, p_query_req->timeout_ms, - p_query_req->retry_cnt, p_sa_req ); + p_query_req->retry_cnt, p_sa_req, flags ); CL_EXIT( AL_DBG_QUERY, g_al_dbg_lvl ); return status; } @@ -389,29 +355,9 @@ query_req_cb( /* Notify the user of the result. */ p_query->pfn_query_cb( &query_rec ); - /* Check for synchronous operation. */ - if( (p_query->flags & IB_FLAGS_SYNC) == IB_FLAGS_SYNC ) - { - cl_event_signal( &p_query->event ); - } - else - { - /* Cleanup from issuing the query. */ - al_remove_query( p_query ); - __free_query( p_query ); - } + /* Cleanup from issuing the query. */ + al_remove_query( p_query ); + cl_free( p_query ); CL_EXIT( AL_DBG_QUERY, g_al_dbg_lvl ); } - - - -static void -__free_query( - IN OUT al_query_t *p_query ) -{ - CL_ASSERT( p_query ); - - cl_event_destroy( &p_query->event ); - cl_free( p_query ); -} diff --git a/branches/fab_cm_branch/core/al/al_query.h b/branches/fab_cm_branch/core/al/al_query.h index 31b58905..9186e9ee 100644 --- a/branches/fab_cm_branch/core/al/al_query.h +++ b/branches/fab_cm_branch/core/al/al_query.h @@ -92,6 +92,7 @@ typedef struct _al_sa_req sa_req_svc_t *p_sa_req_svc; /* For cancellation */ ib_mad_element_t *p_mad_response; ib_mad_element_t *p_mad_request; /* For cancellation */ + KEVENT *p_sync_event; #else /* defined( CL_KERNEL ) */ uint64_t hdl; ual_send_sa_req_ioctl_t ioctl; @@ -108,10 +109,6 @@ typedef struct _al_query { al_sa_req_t sa_req; /* Must be first. */ - /* Used to perform synchronous requests. */ - ib_al_flags_t flags; - cl_event_t event; - ib_al_handle_t h_al; ib_pfn_query_cb_t pfn_query_cb; ib_query_type_t query_type; @@ -130,7 +127,8 @@ al_send_sa_req( IN const net64_t port_guid, IN const uint32_t timeout_ms, IN const uint32_t retry_cnt, - IN const ib_user_query_t* const p_sa_req_data ); + IN const ib_user_query_t* const p_sa_req_data, + IN const ib_al_flags_t flags ); #if defined( CL_KERNEL ) static __inline void diff --git a/branches/fab_cm_branch/core/al/al_reg_svc.c b/branches/fab_cm_branch/core/al/al_reg_svc.c index 2f16f106..2dd09123 100644 --- a/branches/fab_cm_branch/core/al/al_reg_svc.c +++ b/branches/fab_cm_branch/core/al/al_reg_svc.c @@ -47,12 +47,16 @@ __dereg_svc_cb( { ib_reg_svc_handle_t h_reg_svc; - h_reg_svc = PARENT_STRUCT ( p_sa_req, al_reg_svc_t, sa_req ); + /* + * Note that we come into this callback with a reference + * on the registration object. + */ + h_reg_svc = PARENT_STRUCT( p_sa_req, al_reg_svc_t, sa_req ); if( p_mad_response ) ib_put_mad( p_mad_response ); - deref_al_obj( &h_reg_svc->obj ); + h_reg_svc->obj.pfn_destroy( &h_reg_svc->obj, NULL ); } @@ -76,7 +80,7 @@ __sa_dereg_svc( sa_mad_data.comp_mask = ~CL_CONST64(0); if( al_send_sa_req( &h_reg_svc->sa_req, h_reg_svc->port_guid, - 500, 0, &sa_mad_data ) != IB_SUCCESS ) + 500, 0, &sa_mad_data, 0 ) != IB_SUCCESS ) { /* Cleanup from the registration. */ deref_al_obj( &h_reg_svc->obj ); @@ -153,12 +157,15 @@ reg_svc_req_cb( h_reg_svc->pfn_reg_svc_cb( ®_svc_rec ); - /* Check for synchronous operation. */ - if( (h_reg_svc->flags & IB_FLAGS_SYNC) == IB_FLAGS_SYNC ) - cl_event_signal( &h_reg_svc->event ); - - /* Release the reference taken when issuing the request. */ - deref_al_obj( &h_reg_svc->obj ); + if( p_sa_req->status != IB_SUCCESS ) + { + h_reg_svc->obj.pfn_destroy( &h_reg_svc->obj, NULL ); + } + else + { + /* Release the reference taken when issuing the request. */ + deref_al_obj( &h_reg_svc->obj ); + } } @@ -211,7 +218,6 @@ __free_sa_reg( h_sa_reg = PARENT_STRUCT( p_obj, al_reg_svc_t, obj ); destroy_al_obj( p_obj ); - cl_event_destroy( &h_sa_reg->event ); cl_free( h_sa_reg ); AL_EXIT( AL_DBG_SA_REQ ); @@ -224,7 +230,6 @@ sa_reg_svc( IN const ib_reg_svc_req_t* const p_reg_svc_req ) { ib_user_query_t sa_mad_data; - ib_api_status_t status; /* Set the request information. */ h_reg_svc->sa_req.pfn_sa_req_cb = reg_svc_req_cb; @@ -238,9 +243,9 @@ sa_reg_svc( sa_mad_data.comp_mask = p_reg_svc_req->svc_data_mask; sa_mad_data.p_attr = &h_reg_svc->svc_rec; - status = al_send_sa_req( &h_reg_svc->sa_req, h_reg_svc->port_guid, - p_reg_svc_req->timeout_ms, p_reg_svc_req->retry_cnt, &sa_mad_data ); - return status; + return al_send_sa_req( &h_reg_svc->sa_req, h_reg_svc->port_guid, + p_reg_svc_req->timeout_ms, p_reg_svc_req->retry_cnt, &sa_mad_data, + p_reg_svc_req->flags ); } @@ -252,7 +257,6 @@ ib_reg_svc( { ib_reg_svc_handle_t h_sa_reg = NULL; ib_api_status_t status; - cl_status_t cl_status; AL_ENTER( AL_DBG_SA_REQ ); @@ -275,8 +279,6 @@ ib_reg_svc( return IB_INSUFFICIENT_MEMORY; } - h_sa_reg->flags = p_reg_svc_req->flags; - cl_event_construct( &h_sa_reg->event ); construct_al_obj( &h_sa_reg->obj, AL_OBJ_TYPE_H_SA_REG ); status = init_al_obj( &h_sa_reg->obj, p_reg_svc_req->svc_context, TRUE, @@ -299,20 +301,6 @@ ib_reg_svc( return status; } - /* Check for synchronous operation. */ - if( h_sa_reg->flags & IB_FLAGS_SYNC ) - { - cl_status = cl_event_init( &h_sa_reg->event, TRUE ); - if( cl_status != CL_SUCCESS ) - { - status = ib_convert_cl_status( cl_status ); - AL_TRACE_EXIT( AL_DBG_ERROR, - ("cl_init_event failed: %s\n", ib_get_err_str(status)) ); - h_sa_reg->obj.pfn_destroy( &h_sa_reg->obj, NULL ); - return status; - } - } - /* Store the port GUID on which to issue the request. */ h_sa_reg->port_guid = p_reg_svc_req->port_guid; @@ -325,38 +313,18 @@ ib_reg_svc( /* Issue the MAD to the SA. */ status = sa_reg_svc( h_sa_reg, p_reg_svc_req ); - if( status == IB_SUCCESS ) - { - /* If synchronous, wait for the completion. */ - if( h_sa_reg->flags & IB_FLAGS_SYNC ) - { - do - { - cl_status = cl_event_wait_on( - &h_sa_reg->event, EVENT_NO_TIMEOUT, AL_WAIT_ALERTABLE ); - } while( cl_status == CL_NOT_DONE ); - CL_ASSERT( cl_status == CL_SUCCESS ); - - /* Cleanup from issuing the request if it failed. */ - if( h_sa_reg->state == SA_REG_ERROR ) - { - status = h_sa_reg->req_status; - /* The callback released the reference from init_al_obj. */ - ref_al_obj( &h_sa_reg->obj ); - } - } - } - else + if( status != IB_SUCCESS ) { AL_TRACE( AL_DBG_ERROR, ("sa_reg_svc failed: %s\n", ib_get_err_str(status) ) ); h_sa_reg->state = SA_REG_ERROR; - } - if( status != IB_SUCCESS ) h_sa_reg->obj.pfn_destroy( &h_sa_reg->obj, NULL ); + } else + { *ph_reg_svc = h_sa_reg; + } AL_EXIT( AL_DBG_SA_REQ ); return status; diff --git a/branches/fab_cm_branch/core/al/al_reg_svc.h b/branches/fab_cm_branch/core/al/al_reg_svc.h index c2d61c0b..56f6dbc5 100644 --- a/branches/fab_cm_branch/core/al/al_reg_svc.h +++ b/branches/fab_cm_branch/core/al/al_reg_svc.h @@ -51,10 +51,6 @@ typedef struct _al_reg_svc /* Additional status information returned in the registration response. */ ib_net16_t resp_status; - /* Used to perform synchronous requests. */ - ib_al_flags_t flags; - cl_event_t event; - al_sa_reg_state_t state; ib_pfn_reg_svc_cb_t pfn_reg_svc_cb; diff --git a/branches/fab_cm_branch/core/al/kernel/al_proxy_subnet.c b/branches/fab_cm_branch/core/al/kernel/al_proxy_subnet.c index 94b4e689..73eddb1a 100644 --- a/branches/fab_cm_branch/core/al/kernel/al_proxy_subnet.c +++ b/branches/fab_cm_branch/core/al/kernel/al_proxy_subnet.c @@ -214,7 +214,12 @@ proxy_send_sa_req( p_context = p_open_context; p_io_stack = IoGetCurrentIrpStackLocation( h_ioctl ); - if( (uintn_t)p_io_stack->FileObject->FsContext2 != AL_OBJ_TYPE_SA_REQ_SVC ) + /* + * We support SA requests coming in either through the main file object + * or the async file handle. + */ + if( p_io_stack->FileObject->FsContext2 && + (uintn_t)p_io_stack->FileObject->FsContext2 != AL_OBJ_TYPE_SA_REQ_SVC ) { AL_TRACE_EXIT( AL_DBG_ERROR, ("Invalid file object type for request: %d\n", @@ -279,9 +284,14 @@ proxy_send_sa_req( /* Synchronize with callbacks. */ cl_spinlock_acquire( &p_context->h_al->obj.lock ); + /* + * We never pass the user-mode flag when sending SA requests - the + * I/O manager will perform all synchronization to make this IRP sync + * if it needs to. + */ ib_status = al_send_sa_req( p_sa_req, p_ioctl->in.port_guid, p_ioctl->in.timeout_ms, p_ioctl->in.retry_cnt, - &p_ioctl->in.sa_req ); + &p_ioctl->in.sa_req, 0 ); if( ib_status == IB_SUCCESS ) { /* Hold a reference on the proxy context until the request completes. */ diff --git a/branches/fab_cm_branch/core/al/kernel/al_sa_req.c b/branches/fab_cm_branch/core/al/kernel/al_sa_req.c index b4ed77b4..6671f5ba 100644 --- a/branches/fab_cm_branch/core/al/kernel/al_sa_req.c +++ b/branches/fab_cm_branch/core/al/kernel/al_sa_req.c @@ -588,16 +588,35 @@ al_send_sa_req( IN const net64_t port_guid, IN const uint32_t timeout_ms, IN const uint32_t retry_cnt, - IN const ib_user_query_t* const p_sa_req_data ) + IN const ib_user_query_t* const p_sa_req_data, + IN const ib_al_flags_t flags ) { ib_api_status_t status; sa_req_svc_t *p_sa_req_svc; ib_mad_element_t *p_mad_request; ib_mad_t *p_mad_hdr; ib_sa_mad_t *p_sa_mad; + KEVENT event; CL_ENTER( AL_DBG_SA_REQ, g_al_dbg_lvl ); - + + if( flags & IB_FLAGS_SYNC ) + { + if( !cl_is_blockable() ) + { + AL_TRACE_EXIT( AL_DBG_ERROR, + ("Thread context not blockable\n") ); + return IB_INVALID_SETTING; + } + + KeInitializeEvent( &event, NotificationEvent, FALSE ); + p_sa_req->p_sync_event = &event; + } + else + { + p_sa_req->p_sync_event = NULL; + } + /* Locate the sa_req service to issue the sa_req on. */ p_sa_req->p_sa_req_svc = acquire_sa_req_svc( port_guid ); if( !p_sa_req->p_sa_req_svc ) @@ -662,6 +681,11 @@ al_send_sa_req( ib_put_mad( p_mad_request ); deref_al_obj( &p_sa_req->p_sa_req_svc->obj ); } + else if( flags & IB_FLAGS_SYNC ) + { + /* Wait for the MAD completion. */ + KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); + } CL_EXIT( AL_DBG_SA_REQ, g_al_dbg_lvl ); return status; @@ -680,6 +704,7 @@ sa_req_send_comp_cb( { al_sa_req_t *p_sa_req; sa_req_svc_t *p_sa_req_svc; + KEVENT *p_sync_event; CL_ENTER( AL_DBG_SA_REQ, g_al_dbg_lvl ); @@ -698,9 +723,12 @@ sa_req_send_comp_cb( p_sa_req = p_request_mad->send_context1; p_sa_req_svc = p_sa_req->p_sa_req_svc; + p_sync_event = p_sa_req->p_sync_event; p_sa_req->status = convert_wc_status( p_request_mad->status ); p_sa_req->pfn_sa_req_cb( p_sa_req, NULL ); + if( p_sync_event ) + KeSetEvent( p_sync_event, 0, FALSE ); deref_al_obj( &p_sa_req_svc->obj ); } @@ -724,6 +752,7 @@ sa_req_recv_comp_cb( al_sa_req_t *p_sa_req; sa_req_svc_t *p_sa_req_svc; ib_sa_mad_t *p_sa_mad; + KEVENT *p_sync_event; CL_ENTER( AL_DBG_SA_REQ, g_al_dbg_lvl ); @@ -732,6 +761,7 @@ sa_req_recv_comp_cb( p_sa_req = p_mad_response->send_context1; p_sa_req_svc = p_sa_req->p_sa_req_svc; + p_sync_event = p_sa_req->p_sync_event; //*** check for SA redirection... @@ -745,6 +775,8 @@ sa_req_recv_comp_cb( /* Notify the requestor of the result. */ CL_TRACE( AL_DBG_SA_REQ, g_al_dbg_lvl, ("notifying user\n") ); p_sa_req->pfn_sa_req_cb( p_sa_req, p_mad_response ); + if( p_sync_event ) + KeSetEvent( p_sync_event, 0, FALSE ); deref_al_obj( &p_sa_req_svc->obj ); CL_EXIT( AL_DBG_SA_REQ, g_al_dbg_lvl ); diff --git a/branches/fab_cm_branch/core/al/user/ual_sa_req.c b/branches/fab_cm_branch/core/al/user/ual_sa_req.c index 4a989d0d..1450d66c 100644 --- a/branches/fab_cm_branch/core/al/user/ual_sa_req.c +++ b/branches/fab_cm_branch/core/al/user/ual_sa_req.c @@ -161,16 +161,18 @@ free_sa_req_mgr( } - ib_api_status_t al_send_sa_req( IN al_sa_req_t *p_sa_req, IN const net64_t port_guid, IN const uint32_t timeout_ms, IN const uint32_t retry_cnt, - IN const ib_user_query_t* const p_sa_req_data ) + IN const ib_user_query_t* const p_sa_req_data, + IN const ib_al_flags_t flags ) { ib_api_status_t status; + HANDLE h_dev; + DWORD ret_bytes; AL_ENTER( AL_DBG_QUERY ); @@ -190,7 +192,12 @@ al_send_sa_req( p_sa_req->ioctl.in.ph_sa_req = &p_sa_req->hdl; p_sa_req->ioctl.in.p_status = &p_sa_req->status; - if( !DeviceIoControl( gp_sa_req_mgr->h_sa_dev, UAL_SEND_SA_REQ, + if( flags & IB_FLAGS_SYNC ) + h_dev = g_al_device; + else + h_dev = gp_sa_req_mgr->h_sa_dev; + + if( !DeviceIoControl( h_dev, UAL_SEND_SA_REQ, &p_sa_req->ioctl.in, sizeof(p_sa_req->ioctl.in), &p_sa_req->ioctl.out, sizeof(p_sa_req->ioctl.out), NULL, &p_sa_req->ov ) ) @@ -208,8 +215,18 @@ al_send_sa_req( } else { - CL_ASSERT( GetLastError() == ERROR_IO_PENDING ); - status = IB_ERROR; + /* Completed synchronously. */ + if( GetOverlappedResult( h_dev, &p_sa_req->ov, &ret_bytes, FALSE ) ) + { + status = IB_SUCCESS; + /* Process the completion. */ + sa_req_cb( 0, ret_bytes, &p_sa_req->ov ); + } + else + { + sa_req_cb( GetLastError(), 0, &p_sa_req->ov ); + status = IB_ERROR; + } } AL_EXIT( AL_DBG_QUERY ); @@ -217,7 +234,6 @@ al_send_sa_req( } - void CALLBACK sa_req_cb( IN DWORD error_code,