On Tue, Jun 18, 2019 at 08:26:14PM +0300, Leon Romanovsky wrote: > +/** > + * rdma_counter_bind_qp_auto - Check and bind the QP to a counter base on > + * the auto-mode rule > + */ > +int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port) > +{ > + struct rdma_port_counter *port_counter; > + struct ib_device *dev = qp->device; > + struct rdma_counter *counter; > + int ret; > + > + if (!rdma_is_port_valid(dev, port)) > + return -EINVAL; > + > + port_counter = &dev->port_data[port].port_counter; > + if (port_counter->mode.mode != RDMA_COUNTER_MODE_AUTO) > + return 0; > + > + counter = rdma_get_counter_auto_mode(qp, port); > + if (counter) { > + ret = __rdma_counter_bind_qp(counter, qp); > + if (ret) { > + rdma_restrack_put(&counter->res); > + return ret; > + } > + kref_get(&counter->kref); The counter is left in the xarray while the kref is zero, this kref_get is wrong.. Using two kref like things at the same time is a bad idea, the 'rdma_get_counter_auto_mode' should return the kref held, not the restrack get. The restrack_del doesn't happen as long as the kref is positive, so we don't need the retrack thing here.. > + } else { > + counter = rdma_counter_alloc(dev, port, RDMA_COUNTER_MODE_AUTO); > + if (!counter) > + return -ENOMEM; > + > + auto_mode_init_counter(counter, qp, port_counter->mode.mask); > + > + ret = __rdma_counter_bind_qp(counter, qp); > + if (ret) > + goto err_bind; > + > + rdma_counter_res_add(counter, qp); > + if (!rdma_restrack_get(&counter->res)) { > + ret = -EINVAL; > + goto err_get; > + } and this shouldn't be needed as the kref is inited to 1 by the rdma_counter_alloc.. > + } > + > + return 0; > + > +err_get: > + __rdma_counter_unbind_qp(qp); > + __rdma_counter_dealloc(counter); > +err_bind: > + rdma_counter_free(counter); > + return ret; > +} And then all this error unwind and all the twisty __ functions should just be a single kref_put and the release should handle everything. Jason