On Tue, 2017-01-10 at 23:47 +0100, Francois Romieu wrote: > Eric Dumazet <eduma...@google.com> : > > On Tue, Jan 10, 2017 at 9:35 AM, Cong Wang <xiyou.wangc...@gmail.com> wrote: > > > On Mon, Jan 9, 2017 at 9:20 AM, Andrey Konovalov <andreyk...@google.com> > > > wrote: > > > > > > The fix should be straight-forward. Mind to try the attached patch? > > > > > > You forgot to remove schedule() ? > > It may be clearer to split alloc_tx in two parts: only the unsleepable > "if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) {" part of it > contributes to the inner "while (!(skb = alloc_tx(vcc, eff))) {" block. > > See net/atm/common.c > [...] > static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size) > { > struct sk_buff *skb; > struct sock *sk = sk_atm(vcc); > > if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) { > pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n", > sk_wmem_alloc_get(sk), size, sk->sk_sndbuf); > return NULL; > } > while (!(skb = alloc_skb(size, GFP_KERNEL))) > schedule();
Yeah, this code looks quite wrong anyway. We can read it as an infinite loop in some stress conditions or memcg constraints. > The waiting stuff is related to vcc drain but the code makes it look as > if it were also related to skb alloc (it isn't). > > It may be obvious for you but it took me a while to figure what the > code is supposed to achieve. >