[WSD] Fix memory registration code:
authorftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 2 Oct 2006 23:58:56 +0000 (23:58 +0000)
committerftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 2 Oct 2006 23:58:56 +0000 (23:58 +0000)
- Fix access violation if registered memory is freed before
WSD switch calls to deregister.
- No need to set IB_AC_LOCAL_WRITE for MEM_READ registrations.

git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@510 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

ulp/wsd/user/extensions.c
ulp/wsd/user/ibsp_mem.c

index 3de9b07..6af9f96 100644 (file)
@@ -199,20 +199,18 @@ IBSPRegisterRdmaMemory(
                return SOCKET_ERROR;\r
        }\r
 \r
-       access_ctrl = IB_AC_LOCAL_WRITE;\r
-\r
        switch( dwFlags )\r
        {\r
        case MEM_READ:\r
-               access_ctrl |= IB_AC_RDMA_READ;\r
+               access_ctrl = IB_AC_RDMA_READ;\r
                break;\r
 \r
        case MEM_WRITE:\r
-               access_ctrl |= IB_AC_RDMA_WRITE;\r
+               access_ctrl = IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE;\r
                break;\r
 \r
        case MEM_READWRITE:\r
-               access_ctrl |= (IB_AC_RDMA_READ | IB_AC_RDMA_WRITE);\r
+               access_ctrl = IB_AC_LOCAL_WRITE | IB_AC_RDMA_READ | IB_AC_RDMA_WRITE;\r
                break;\r
 \r
        default:\r
index 3e13c7f..ea05e46 100644 (file)
@@ -205,7 +205,10 @@ static inline int __ibsp_dereg_mem_mr(
 {\r
        IBSP_ENTER( IBSP_DBG_MEM );\r
 \r
-       cl_qlist_remove_item( &node->p_reg->node_list, &node->mr_item );\r
+       // Underlying registration could be freed before the node.\r
+       if( node->p_reg )\r
+               cl_qlist_remove_item( &node->p_reg->node_list, &node->mr_item );\r
+\r
        cl_qlist_remove_item( &node->s->mr_list, &node->socket_item );\r
 \r
        HeapFree( g_ibsp.heap, 0, node );\r
@@ -257,13 +260,18 @@ ibsp_dereg_hca(
                struct memory_reg *p_reg = PARENT_STRUCT(item, struct memory_reg, item);\r
                ib_api_status_t status;\r
 \r
-               while( cl_qlist_count( &p_reg->node_list ) )\r
+               /*\r
+                * Clear the pointer from the node to this registration.  No need\r
+                * to remove from the list as we're about to free the registration.\r
+                */\r
+               for( item = cl_qlist_head( &p_reg->node_list );\r
+                       item != cl_qlist_end( &p_reg->node_list );\r
+                       item = cl_qlist_next( item ) )\r
                {\r
                        struct memory_node *p_node =\r
-                               PARENT_STRUCT( cl_qlist_head( &p_reg->node_list ),\r
-                               struct memory_node, mr_item );\r
+                               PARENT_STRUCT( item, struct memory_node, mr_item );\r
 \r
-                       __ibsp_dereg_mem_mr( p_node );\r
+                       p_node->p_reg = NULL;\r
                }\r
 \r
                IBSP_TRACE2( IBSP_DBG_MEM, ("unpinning ,memory reg %p\n", p_reg) );\r
@@ -336,12 +344,14 @@ ibsp_hca_flush_mr_cache(
        IBSP_ENTER( IBSP_DBG_MEM );\r
 \r
        cl_spinlock_acquire( &p_hca->rdma_mem_list.mutex );\r
-       for( p_item = cl_qlist_head( &p_hca->rdma_mem_list.list );\r
-               p_item != cl_qlist_end( &p_hca->rdma_mem_list.list );\r
-               p_item = cl_qlist_next( p_item ) )\r
+       p_item = cl_qlist_head( &p_hca->rdma_mem_list.list );\r
+       while( p_item != cl_qlist_end( &p_hca->rdma_mem_list.list ) )\r
        {\r
                p_reg = PARENT_STRUCT( p_item, struct memory_reg, item );\r
 \r
+               /* Move to the next item now so we can remove the current. */\r
+               p_item = cl_qlist_next( p_item );\r
+\r
                if( lpvAddress > p_reg->type.vaddr ||\r
                        ((uintn_t)lpvAddress) + Size <\r
                        ((uintn_t)(uint64_t)p_reg->type.vaddr) + p_reg->type.length )\r
@@ -349,19 +359,21 @@ ibsp_hca_flush_mr_cache(
                        continue;\r
                }\r
 \r
-               /* Release all socket's nodes that reference this registration. */\r
-               while( cl_qlist_count( &p_reg->node_list ) )\r
+               /*\r
+                * Clear the pointer from all sockets' nodes to this registration.\r
+                * No need to remove from the list as we're about to free the\r
+                * registration.\r
+                */\r
+               for( p_item = cl_qlist_head( &p_reg->node_list );\r
+                       p_item != cl_qlist_end( &p_reg->node_list );\r
+                       p_item = cl_qlist_next( p_item ) )\r
                {\r
-                       struct memory_node      *p_node =\r
-                               PARENT_STRUCT( cl_qlist_head( &p_reg->node_list ),\r
-                               struct memory_node, mr_item );\r
+                       struct memory_node *p_node =\r
+                               PARENT_STRUCT( p_item, struct memory_node, mr_item );\r
 \r
-                       __ibsp_dereg_mem_mr( p_node );\r
+                       p_node->p_reg = NULL;\r
                }\r
 \r
-               /* Move to the previous item so the for loop properly moves forward. */\r
-               p_item = cl_qlist_prev( p_item );\r
-\r
                cl_qlist_remove_item( &p_hca->rdma_mem_list.list, &p_reg->item );\r
 \r
                status = ib_dereg_mr( p_reg->mr_handle );\r