]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: Add reset all conns for a source address to CONN_RESET
authorSantosh Shilimkar <santosh.shilimkar@oracle.com>
Wed, 23 Mar 2016 04:51:49 +0000 (21:51 -0700)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Tue, 31 May 2016 16:03:33 +0000 (09:03 -0700)
RDS_CONN_RESET SO gets enhanced to support reseting all
connections associated with a local address.

$rds-stress -r <SRC_IP> -s 0 --reset

Orabug: 23222944

Reported-by: Bang Ngyen <bang.nguyen@oracle.com>
Acked-by: Bang Ngyen <bang.nguyen@oracle.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
net/rds/af_rds.c
net/rds/connection.c
net/rds/rds.h

index f3948435c1b91208fd1e5123613646876b4b241f..4b3e728a4c3cc37f875629247ed11c54a34926b4 100644 (file)
@@ -327,6 +327,7 @@ static int rds_user_reset(struct rds_sock *rs, char __user *optval, int optlen)
 {
        struct rds_reset reset;
        struct rds_connection *conn;
+       LIST_HEAD(s_addr_conns);
 
        if (optlen != sizeof(struct rds_reset))
                return -EINVAL;
@@ -335,6 +336,23 @@ static int rds_user_reset(struct rds_sock *rs, char __user *optval, int optlen)
                                sizeof(struct rds_reset)))
                return -EFAULT;
 
+       /* Reset all conns associated with source addr */
+       if (reset.dst.s_addr ==  0) {
+               pr_info("RDS: Reset ALL conns for Source %pI4\n",
+                        &reset.src.s_addr);
+
+               rds_conn_laddr_list(reset.src.s_addr, &s_addr_conns);
+               if (list_empty(&s_addr_conns))
+                       goto done;
+
+               list_for_each_entry(conn, &s_addr_conns, c_laddr_node)
+                       if (conn) {
+                               conn->c_drop_source = 1;
+                               rds_conn_drop(conn);
+                       }
+               goto done;
+       }
+
        conn = rds_conn_find(sock_net(rds_rs_to_sk(rs)),
                             reset.src.s_addr, reset.dst.s_addr,
                        rs->rs_transport, reset.tos);
@@ -347,7 +365,7 @@ static int rds_user_reset(struct rds_sock *rs, char __user *optval, int optlen)
                conn->c_drop_source = DR_USER_RESET;
                rds_conn_drop(conn);
        }
-
+done:
        return 0;
 }
 
index 0b7d1e2ee587617b7fa960fc6e9c78509db2e6a3..c4b885c87b63a0cda5b6dd590dfb2cb8db2ecd35 100644 (file)
@@ -91,6 +91,24 @@ static struct rds_connection *rds_conn_lookup(struct net *net,
        return ret;
 }
 
+void rds_conn_laddr_list(__be32 laddr, struct list_head *laddr_conns)
+{
+       struct rds_connection *conn;
+       struct hlist_head *head;
+       int i;
+
+       rcu_read_lock();
+
+       for (i = 0, head = rds_conn_hash; i < ARRAY_SIZE(rds_conn_hash);
+            i++, head++) {
+               hlist_for_each_entry_rcu(conn, head, c_hash_node)
+                       if (conn->c_laddr == laddr)
+                               list_add(&conn->c_laddr_node, laddr_conns);
+       }
+
+       rcu_read_unlock();
+}
+
 /*
  * This is called by transports as they're bringing down a connection.
  * It clears partial message state so that the transport can start sending
index a3d6284edd2a72e153759c018996adba701abc66..7237bc58fb9d773b6517c8374db32db3e4598715 100644 (file)
@@ -287,6 +287,7 @@ struct rds_connection {
        unsigned int            c_route_resolved;
 
        enum rds_conn_drop_src  c_drop_source;
+       struct list_head        c_laddr_node;
 };
 
 static inline
@@ -838,6 +839,7 @@ void rds_conn_shutdown(struct rds_connection *conn, int restart);
 void rds_conn_destroy(struct rds_connection *conn);
 void rds_conn_reset(struct rds_connection *conn);
 void rds_conn_drop(struct rds_connection *conn);
+void rds_conn_laddr_list(__be32 laddr, struct list_head *laddr_conns);
 void rds_conn_connect_if_down(struct rds_connection *conn);
 void rds_for_each_conn_info(struct socket *sock, unsigned int len,
                          struct rds_info_iterator *iter,