On Mon, Apr 04, 2022 at 03:27:26PM +0300, Leon Romanovsky wrote: > +static int compare_netdev_and_ip(int ifindex_a, struct sockaddr *sa, > + int ifindex_b, struct sockaddr *sb) > +{ > + if (ifindex_a != ifindex_b) > + return ifindex_a - ifindex_b; These subtraction tricks don't work if the value can overflow INT_MAX - INT_MIN == undefined > +static int cma_add_id_to_tree(struct rdma_id_private *node_id_priv) > +{ > + struct rb_node **new = &id_table.rb_node, *parent = NULL; This read of rb_node has to be under the spinlock > + struct id_table_entry *this, *node; > + struct rdma_id_private *id_priv; > + unsigned long flags; > + int result; > + > + node = kzalloc(sizeof(*node), GFP_KERNEL); > + if (!node) > + return -ENOMEM; > + > + spin_lock_irqsave(&id_table_lock, flags); > + while (*new) { > + this = container_of(*new, struct id_table_entry, rb_node); Because rebalacing can alter the head > + id_priv = list_first_entry( > + &this->id_list, struct rdma_id_private, id_list_entry); > + result = compare_netdev_and_ip( > + node_id_priv->id.route.addr.dev_addr.bound_dev_if, > + cma_dst_addr(node_id_priv), > + id_priv->id.route.addr.dev_addr.bound_dev_if, > + cma_dst_addr(id_priv)); This pattern keeps repeating, one of the arguments to compare should just be the id_table_entry * and do the list_first/etc inside the compare. Jason