-----"Jason Gunthorpe" <jgg@xxxxxxxxxxxx> wrote: ----- >To: "Leon Romanovsky" <leon@xxxxxxxxxx>, "Bernard Metzler" ><bmt@xxxxxxxxxxxxxx> >From: "Jason Gunthorpe" <jgg@xxxxxxxxxxxx> >Date: 07/10/2019 07:52PM >Cc: "Stephen Rothwell" <sfr@xxxxxxxxxxxxxxxx>, "Doug Ledford" ><dledford@xxxxxxxxxx>, "David Miller" <davem@xxxxxxxxxxxxx>, >"Networking" <netdev@xxxxxxxxxxxxxxx>, "Linux Next Mailing List" ><linux-next@xxxxxxxxxxxxxxx>, "Linux Kernel Mailing List" ><linux-kernel@xxxxxxxxxxxxxxx> >Subject: [EXTERNAL] Re: linux-next: build failure after merge of the >net-next tree > >On Tue, Jul 09, 2019 at 09:43:46AM +0300, Leon Romanovsky wrote: >> On Tue, Jul 09, 2019 at 01:56:36PM +1000, Stephen Rothwell wrote: >> > Hi all, >> > >> > After merging the net-next tree, today's linux-next build (x86_64 >> > allmodconfig) failed like this: >> > >> > drivers/infiniband/sw/siw/siw_cm.c: In function >'siw_create_listen': >> > drivers/infiniband/sw/siw/siw_cm.c:1978:3: error: implicit >declaration of function 'for_ifa'; did you mean 'fork_idle'? >[-Werror=implicit-function-declaration] >> > for_ifa(in_dev) >> > ^~~~~~~ >> > fork_idle >> > drivers/infiniband/sw/siw/siw_cm.c:1978:18: error: expected ';' >before '{' token >> > for_ifa(in_dev) >> > ^ >> > ; >> > { >> > ~ >> > >> > Caused by commit >> > >> > 6c52fdc244b5 ("rdma/siw: connection management") >> > >> > from the rdma tree. I don't know why this didn't fail after I >mereged >> > that tree. >> >> I had the same question, because I have this fix for a couple of >days already. >> >> From 56c9e15ec670af580daa8c3ffde9503af3042d67 Mon Sep 17 00:00:00 >2001 >> From: Leon Romanovsky <leonro@xxxxxxxxxxxx> >> Date: Sun, 7 Jul 2019 10:43:42 +0300 >> Subject: [PATCH] Fixup to build SIW issue >> >> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> >> drivers/infiniband/sw/siw/siw_cm.c | 5 ++--- >> 1 file changed, 2 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/infiniband/sw/siw/siw_cm.c >b/drivers/infiniband/sw/siw/siw_cm.c >> index 8e618cb7261f..c883bf514341 100644 >> +++ b/drivers/infiniband/sw/siw/siw_cm.c >> @@ -1954,6 +1954,7 @@ static void siw_drop_listeners(struct >iw_cm_id *id) >> int siw_create_listen(struct iw_cm_id *id, int backlog) >> { >> struct net_device *dev = to_siw_dev(id->device)->netdev; >> + const struct in_ifaddr *ifa; >> int rv = 0, listeners = 0; >> >> siw_dbg(id->device, "id 0x%p: backlog %d\n", id, backlog); >> @@ -1975,8 +1976,7 @@ int siw_create_listen(struct iw_cm_id *id, >int backlog) >> id, &s_laddr.sin_addr, ntohs(s_laddr.sin_port), >> &s_raddr->sin_addr, ntohs(s_raddr->sin_port)); >> >> - for_ifa(in_dev) >> - { >> + in_dev_for_each_ifa_rcu(ifa, in_dev) { >> if (ipv4_is_zeronet(s_laddr.sin_addr.s_addr) || > >Hum. There is no rcu lock held here and we can't use RCU anyhow as >siw_listen_address will sleep. > >I think this needs to use rtnl, as below. Bernard, please urgently >confirm. Thanks > Hi Jason, That listen will not sleep. The socket is just marked listening. Accepting a new connection is handled asynchronously by a work handler, kicked by a socket callback (siw_cm_llp_state_change). But, I think you are correct, we are missing the rcu_read_lock/unlock around that iteration. Could we please add that (see below)? Thanks very much! Bernard. diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c index c883bf514341..c5c060103993 100644 --- a/drivers/infiniband/sw/siw/siw_cm.c +++ b/drivers/infiniband/sw/siw/siw_cm.c @@ -1976,6 +1976,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog) id, &s_laddr.sin_addr, ntohs(s_laddr.sin_port), &s_raddr->sin_addr, ntohs(s_raddr->sin_port)); + rcu_read_lock(); in_dev_for_each_ifa_rcu(ifa, in_dev) { if (ipv4_is_zeronet(s_laddr.sin_addr.s_addr) || s_laddr.sin_addr.s_addr == ifa->ifa_address) { @@ -1988,6 +1989,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog) listeners++; } } + rcu_read_unlock(); in_dev_put(in_dev); } else if (id->local_addr.ss_family == AF_INET6) { struct inet6_dev *in6_dev = in6_dev_get(dev); >diff --git a/drivers/infiniband/sw/siw/siw_cm.c >b/drivers/infiniband/sw/siw/siw_cm.c >index 8e618cb7261f62..ee98e96a5bfaba 100644 >--- a/drivers/infiniband/sw/siw/siw_cm.c >+++ b/drivers/infiniband/sw/siw/siw_cm.c >@@ -1965,6 +1965,7 @@ int siw_create_listen(struct iw_cm_id *id, int >backlog) > */ > if (id->local_addr.ss_family == AF_INET) { > struct in_device *in_dev = in_dev_get(dev); >+ const struct in_ifaddr *ifa; > struct sockaddr_in s_laddr, *s_raddr; > > memcpy(&s_laddr, &id->local_addr, sizeof(s_laddr)); >@@ -1975,8 +1976,8 @@ int siw_create_listen(struct iw_cm_id *id, int >backlog) > id, &s_laddr.sin_addr, ntohs(s_laddr.sin_port), > &s_raddr->sin_addr, ntohs(s_raddr->sin_port)); > >- for_ifa(in_dev) >- { >+ rtnl_lock(); >+ in_dev_for_each_ifa_rtnl(ifa, in_dev) { > if (ipv4_is_zeronet(s_laddr.sin_addr.s_addr) || > s_laddr.sin_addr.s_addr == ifa->ifa_address) { > s_laddr.sin_addr.s_addr = ifa->ifa_address; >@@ -1988,7 +1989,7 @@ int siw_create_listen(struct iw_cm_id *id, int >backlog) > listeners++; > } > } >- endfor_ifa(in_dev); >+ rtnl_unlock(); > in_dev_put(in_dev); > } else if (id->local_addr.ss_family == AF_INET6) { > struct inet6_dev *in6_dev = in6_dev_get(dev); > >