[ofa-general] SDP memory allocation policy problem?

Nathan Dauchy Nathan.Dauchy at noaa.gov
Tue Sep 25 15:49:55 PDT 2007


Is there anyone among the OFED development team that is looking into
this issue?  I believe that it is causing nodes to hang at our site.  We
are running ofed-1.2 and the 2.6.9-55.ELsmp kernel.

Workarounds or even untested patches would be appreciated.

Thanks!

-Nathan


Ken Phillips wrote:
> Greetings,
> 
> Teammates here report the following:
> 
> Problem
> 
> The method SDP uses to allocate socket buffers may cause the
> node to hang under memory pressure.
> 
> Details
> 
> Each kernel level socket has an allocation flag to specify the
> memory allocation policy for socket buffers, the default is GFP_ATOMIC
> (or GFP_KERNEL for SDP).  If the caller creates a socket with the
> policy set to GFP_NOFS or GFP_NOIO this should be the allocation
> policy used by the SDP layer.
> 
> The problem we are seeing is that if a node is under load, and
> a memory allocation fails (say in sock_sendmsg()), the kernel will
> use the allocation policy to decide how to proceed with the allocation.
> If GFP_KERNEL is specified, then the kernel may attempt to free pages
> through the iSCSI block device that is making the socket call, which
> would result in a deadlock.  Use of GFP_NOIO should prevent the kernel
> from using the IO backend to free memory resources.
> 
> here is a sample stack trace from Alt-Sysrq during one of these
> lockups,
> 
>> tx_worker     D ffffff0014d14000     0 10195      1         10196 10194
>> (L-TLB)
>> 00000100707e98d8 0000000000000046 0000000000000004 0000000000000212
>> 0000000000000212 ffffffffa018ccae 0000000000000246 0000000000000246
>> 000001007873c7f0 0000000000000320
>> Call Trace:<ffffffffa018ccae>{:ib_mthca:mthca_poll_cq+2258}
>> <ffffffff8030ad5c>{schedule_timeout+224}
>> <ffffffff802a9db7>{lock_sock+152}
>> <ffffffff80135756>{autoremove_wake_function+0}
>> <ffffffffa0538b13>{:ib_sdp:sdp_poll_cq+58}
>> <ffffffff80135756>{autoremove_wake_function+0}
>> <ffffffff802a9dfd>{release_sock+16}
>> <ffffffffa0534b18>{:ib_sdp:sdp_sendmsg+33}
>> <ffffffff802a730f>{sock_sendmsg+271}
>> <ffffffffa05386ad>{:ib_sdp:sdp_post_sends+619}
>> <ffffffff802a9dfd>{release_sock+16}
>> <ffffffffa05353a5>{:ib_sdp:sdp_sendmsg+2222}
>> <ffffffff80135756>{autoremove_wake_function+0}
>> <ffffffffa057708f>{:rs_iscsi:iscsi_sock_msg+1265}
>> <ffffffffa057708b>{:rs_iscsi:iscsi_sock_msg+1261}
>> <ffffffff80132159>{recalc_task_prio+337}
>> <ffffffffa055bfdb>{:rs_iscsi:scsi_command_i+5283}
>> <ffffffff8030a2c9>{thread_return+0}
>> <ffffffff8030a321>{thread_return+88}
>> <ffffffff8013fdf7>{del_timer+107}
>> <ffffffff8013feb4>{del_singleshot_timer_sync+9}
>> <ffffffff8030adf3>{schedule_timeout+375}
>> <ffffffffa056829e>{:rs_iscsi:tx_worker_proc_i+6819}
>> <ffffffff80110f47>{child_rip+8}
>> <ffffffffa05667fb>{:rs_iscsi:tx_worker_proc_i+0}
>> <ffffffff80110f3f>{child_rip+0}
>>
>>
> 
> We still don't know the scope of changes to be made, but we think,
> at minimum that some of the memory allocation in SDP should be changed,
> for example.
> 
> diff -Naur old/drivers/infiniband/ulp/sdp/sdp_bcopy.c
> new/drivers/infiniband/ulp/sdp/sdp_bcopy.c
> --- old/drivers/infiniband/ulp/sdp/sdp_bcopy.c    2007-06-21
> 10:38:47.000000000 -0400
> +++ new/drivers/infiniband/ulp/sdp/sdp_bcopy.c    2007-08-31
> 12:25:58.000000000 -0400
> @@ -224,13 +224,27 @@
> 
>      /* Now, allocate and repost recv */
>      /* TODO: allocate from cache */
> +
> +#if (PROPOSED_SDP_FIX == 1)
> +    skb = sk_stream_alloc_skb(&ssk->isk.sk, SDP_HEAD_SIZE,
> +        (ssk->isk.sk.sk_allocation == 0) ? (GFP_KERNEL) :
> +        ssk->isk.sk.sk_allocation);
> +#else
>      skb = sk_stream_alloc_skb(&ssk->isk.sk, SDP_HEAD_SIZE,
>                    GFP_KERNEL);
> +#endif
>      /* FIXME */
>      BUG_ON(!skb);
>      h = (struct sdp_bsdh *)skb->head;
>      for (i = 0; i < ssk->recv_frags; ++i) {
> +#if (PROPOSED_SDP_FIX == 1)
> +        page = alloc_pages((ssk->isk.sk.sk_allocation == 0)
> +            ? (GFP_HIGHUSER) :
> +            (ssk->isk.sk.sk_allocation | (__GFP_HIGHMEM)),
> +            0);
> +#else
>          page = alloc_pages(GFP_HIGHUSER, 0);
> +#endif
>          BUG_ON(!page);
>          frag = &skb_shinfo(skb)->frags[i];
>          frag->page                = page;
> @@ -406,10 +420,18 @@
>          ssk->tx_head - ssk->tx_tail < SDP_TX_SIZE) {
>          struct sdp_chrecvbuf *resp_size;
>          ssk->recv_request = 0;
> +#if (PROPOSED_SDP_FIX == 1)
> +        skb = sk_stream_alloc_skb(&ssk->isk.sk,
> +            sizeof(struct sdp_bsdh) +
> +            sizeof(*resp_size),
> +            (ssk->isk.sk.sk_allocation == 0) ? (GFP_KERNEL) :
> +            ssk->isk.sk.sk_allocation);
> +#else
>          skb = sk_stream_alloc_skb(&ssk->isk.sk,
>                        sizeof(struct sdp_bsdh) +
>                        sizeof(*resp_size),
>                        GFP_KERNEL);
> +#endif
>          /* FIXME */
>          BUG_ON(!skb);
>          resp_size = (struct sdp_chrecvbuf *)skb_put(skb, sizeof *resp_size);
> @@ -431,10 +453,18 @@
>          ssk->tx_head > ssk->sent_request_head + SDP_RESIZE_WAIT &&
>          ssk->tx_head - ssk->tx_tail < SDP_TX_SIZE) {
>          struct sdp_chrecvbuf *req_size;
> +#if (PROPOSED_SDP_FIX == 1)
> +        skb = sk_stream_alloc_skb(&ssk->isk.sk,
> +            sizeof(struct sdp_bsdh) +
> +            sizeof(*req_size),
> +            (ssk->isk.sk.sk_allocation == 0) ? (GFP_KERNEL) :
> +            ssk->isk.sk.sk_allocation);
> +#else
>          skb = sk_stream_alloc_skb(&ssk->isk.sk,
>                        sizeof(struct sdp_bsdh) +
>                        sizeof(*req_size),
>                        GFP_KERNEL);
> +#endif
>          /* FIXME */
>          BUG_ON(!skb);
>          ssk->sent_request = SDP_MAX_SEND_SKB_FRAGS * PAGE_SIZE;
> @@ -463,9 +493,16 @@
>              (TCPF_FIN_WAIT1 | TCPF_LAST_ACK)) &&
>          !ssk->isk.sk.sk_send_head &&
>          ssk->bufs) {
> +#if (PROPOSED_SDP_FIX == 1)
> +        skb = sk_stream_alloc_skb(&ssk->isk.sk,
> +            sizeof(struct sdp_bsdh),
> +            (ssk->isk.sk.sk_allocation == 0) ? (GFP_KERNEL) :
> +            ssk->isk.sk.sk_allocation);
> +#else
>          skb = sk_stream_alloc_skb(&ssk->isk.sk,
>                        sizeof(struct sdp_bsdh),
>                        GFP_KERNEL);
> +#endif
>          /* FIXME */
>          BUG_ON(!skb);
>          sdp_post_send(ssk, skb, SDP_MID_DISCONN);
> diff -Naur old/drivers/infiniband/ulp/sdp/sdp.h
> new/drivers/infiniband/ulp/sdp/sdp.h
> --- old/drivers/infiniband/ulp/sdp/sdp.h    2007-06-21 10:38:47.000000000 -0400
> +++ new/drivers/infiniband/ulp/sdp/sdp.h    2007-08-31 12:25:45.000000000 -0400
> @@ -7,6 +7,8 @@
>  #include <net/tcp.h> /* For urgent data flags */
>  #include <rdma/ib_verbs.h>
> 
> +#define PROPOSED_SDP_FIX 1
> +
>  #define sdp_printk(level, sk, format, arg...)                \
>      printk(level "sdp_sock(%d:%d): " format,             \
>             (sk) ? inet_sk(sk)->num : -1,                 \
> 
> 
> 
> 
> ---------------------
> Best Regards
> K Phillips
> _______________________________________________
> general mailing list
> general at lists.openfabrics.org
> http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general
> 
> To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general




More information about the general mailing list