From: Dan Duval Date: Wed, 9 Dec 2015 22:13:36 +0000 (-0500) Subject: Revert "netlink: Replace rhash_portid with bound" X-Git-Tag: v4.1.12-92~218^2~1 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=14ad67a77a41a2ebd64f4260dd707fbe6109e193;p=users%2Fjedix%2Flinux-maple.git Revert "netlink: Replace rhash_portid with bound" Orabug: 22284865 This reverts commit d48623677191e0f035d7afd344f92cf880b01f8e. That commit, along with 4e27762, have been shown to provoke a hang in the Oracle Real Application Clusters (RAC) silent-installation procedure. Signed-off-by: Dan Duval --- diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d139c43ac6e5..eb54d50ecd51 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1017,7 +1017,7 @@ static inline int netlink_compare(struct rhashtable_compare_arg *arg, const struct netlink_compare_arg *x = arg->key; const struct netlink_sock *nlk = ptr; - return nlk->portid != x->portid || + return nlk->rhash_portid != x->portid || !net_eq(sock_net(&nlk->sk), read_pnet(&x->pnet)); } @@ -1043,7 +1043,7 @@ static int __netlink_insert(struct netlink_table *table, struct sock *sk) { struct netlink_compare_arg arg; - netlink_compare_arg_init(&arg, sock_net(sk), nlk_sk(sk)->portid); + netlink_compare_arg_init(&arg, sock_net(sk), nlk_sk(sk)->rhash_portid); return rhashtable_lookup_insert_key(&table->hash, &arg, &nlk_sk(sk)->node, netlink_rhashtable_params); @@ -1096,8 +1096,8 @@ static int netlink_insert(struct sock *sk, u32 portid) lock_sock(sk); - err = nlk_sk(sk)->portid == portid ? 0 : -EBUSY; - if (nlk_sk(sk)->bound) + err = -EBUSY; + if (nlk_sk(sk)->portid) goto err; err = -ENOMEM; @@ -1105,7 +1105,7 @@ static int netlink_insert(struct sock *sk, u32 portid) unlikely(atomic_read(&table->hash.nelems) >= UINT_MAX)) goto err; - nlk_sk(sk)->portid = portid; + nlk_sk(sk)->rhash_portid = portid; sock_hold(sk); err = __netlink_insert(table, sk); @@ -1120,9 +1120,7 @@ static int netlink_insert(struct sock *sk, u32 portid) sock_put(sk); } - /* We need to ensure that the socket is hashed and visible. */ - smp_wmb(); - nlk_sk(sk)->bound = portid; + nlk_sk(sk)->portid = portid; err: release_sock(sk); @@ -1503,7 +1501,6 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; int err; long unsigned int groups = nladdr->nl_groups; - bool bound; if (addr_len < sizeof(struct sockaddr_nl)) return -EINVAL; @@ -1520,14 +1517,9 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, return err; } - bound = nlk->bound; - if (bound) { - /* Ensure nlk->portid is up-to-date. */ - smp_rmb(); - + if (nlk->portid) if (nladdr->nl_pid != nlk->portid) return -EINVAL; - } if (nlk->netlink_bind && groups) { int group; @@ -1543,10 +1535,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, } } - /* No need for barriers here as we return to user-space without - * using any of the bound attributes. - */ - if (!bound) { + if (!nlk->portid) { err = nladdr->nl_pid ? netlink_insert(sk, nladdr->nl_pid) : netlink_autobind(sock); @@ -1594,10 +1583,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) return -EPERM; - /* No need for barriers here as we return to user-space without - * using any of the bound attributes. - */ - if (!nlk->bound) + if (!nlk->portid) err = netlink_autobind(sock); if (err == 0) { @@ -2354,13 +2340,10 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) dst_group = nlk->dst_group; } - if (!nlk->bound) { + if (!nlk->portid) { err = netlink_autobind(sock); if (err) goto out; - } else { - /* Ensure nlk is hashed and visible. */ - smp_rmb(); } /* It's a really convoluted way for userland to ask for mmaped @@ -3195,7 +3178,7 @@ static inline u32 netlink_hash(const void *data, u32 len, u32 seed) const struct netlink_sock *nlk = data; struct netlink_compare_arg arg; - netlink_compare_arg_init(&arg, sock_net(&nlk->sk), nlk->portid); + netlink_compare_arg_init(&arg, sock_net(&nlk->sk), nlk->rhash_portid); return jhash2((u32 *)&arg, netlink_compare_arg_len / sizeof(u32), seed); } diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index 14437d9b1965..80b2b7526dfd 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h @@ -25,6 +25,7 @@ struct netlink_ring { struct netlink_sock { /* struct sock has to be the first member of netlink_sock */ struct sock sk; + u32 rhash_portid; u32 portid; u32 dst_portid; u32 dst_group; @@ -35,7 +36,6 @@ struct netlink_sock { unsigned long state; size_t max_recvmsg_len; wait_queue_head_t wait; - bool bound; bool cb_running; struct netlink_callback cb; struct mutex *cb_mutex;