rds: ib: Increment i_fastreg_wrs before bailing out
authorHåkon Bugge <haakon.bugge@oracle.com>
Thu, 11 Sep 2025 13:33:34 +0000 (15:33 +0200)
committerJakub Kicinski <kuba@kernel.org>
Mon, 15 Sep 2025 23:47:53 +0000 (16:47 -0700)
We need to increment i_fastreg_wrs before we bail out from
rds_ib_post_reg_frmr().

We have a fixed budget of how many FRWR operations that can be
outstanding using the dedicated QP used for memory registrations and
de-registrations. This budget is enforced by the atomic_t
i_fastreg_wrs. If we bail out early in rds_ib_post_reg_frmr(), we will
"leak" the possibility of posting an FRWR operation, and if that
accumulates, no FRWR operation can be carried out.

Fixes: 1659185fb4d0 ("RDS: IB: Support Fastreg MR (FRMR) memory registration mode")
Fixes: 3a2886cca703 ("net/rds: Keep track of and wait for FRWR segments in use upon shutdown")
Cc: stable@vger.kernel.org
Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Link: https://patch.msgid.link/20250911133336.451212-1-haakon.bugge@oracle.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/rds/ib_frmr.c

index 28c1b00..bd86119 100644 (file)
@@ -133,12 +133,15 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
 
        ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_dma_len,
                                &off, PAGE_SIZE);
-       if (unlikely(ret != ibmr->sg_dma_len))
-               return ret < 0 ? ret : -EINVAL;
+       if (unlikely(ret != ibmr->sg_dma_len)) {
+               ret = ret < 0 ? ret : -EINVAL;
+               goto out_inc;
+       }
 
-       if (cmpxchg(&frmr->fr_state,
-                   FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE)
-               return -EBUSY;
+       if (cmpxchg(&frmr->fr_state, FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE) {
+               ret = -EBUSY;
+               goto out_inc;
+       }
 
        atomic_inc(&ibmr->ic->i_fastreg_inuse_count);
 
@@ -166,11 +169,10 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
                /* Failure here can be because of -ENOMEM as well */
                rds_transition_frwr_state(ibmr, FRMR_IS_INUSE, FRMR_IS_STALE);
 
-               atomic_inc(&ibmr->ic->i_fastreg_wrs);
                if (printk_ratelimit())
                        pr_warn("RDS/IB: %s returned error(%d)\n",
                                __func__, ret);
-               goto out;
+               goto out_inc;
        }
 
        /* Wait for the registration to complete in order to prevent an invalid
@@ -179,8 +181,10 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
         */
        wait_event(frmr->fr_reg_done, !frmr->fr_reg);
 
-out:
+       return ret;
 
+out_inc:
+       atomic_inc(&ibmr->ic->i_fastreg_wrs);
        return ret;
 }