@@ -2077,9 +2077,20 @@ migr_type2res(struct migrate_pool_tls *tls, int res_type)
20772077 if (rmg -> rmg_bkt_type == MIGR_BUCKET_MAP ) {
20782078 idx = dmi -> dmi_tgt_id / rmg -> rmg_bkt_size ;
20792079 D_ASSERT (idx < rmg -> rmg_bkt_nr );
2080- } else /* rotation */ {
2081- idx = atomic_fetch_add (& rmg -> rmg_bkt_selector , 1 );
2082- idx %= rmg -> rmg_bkt_nr ;
2080+ } else { /* MIGR_BUCKET_ROTATE */
2081+ struct migr_resource * * cached ;
2082+
2083+ /* For the rotation type, hold() and release() must use the same bucket.
2084+ * Cache the chosen bucket in the per-pool TLS so every call from the same
2085+ * ULT/pool always lands on the same bucket, avoiding hold/release mismatch.
2086+ */
2087+ cached = (res_type == MIGR_OBJ ) ? & tls -> mpt_obj_res : & tls -> mpt_key_res ;
2088+ if (* cached == NULL ) {
2089+ idx = atomic_fetch_add (& rmg -> rmg_bkt_selector , 1 );
2090+ idx %= rmg -> rmg_bkt_nr ;
2091+ * cached = & rmg -> rmg_res_buckets [idx ];
2092+ }
2093+ return * cached ;
20832094 }
20842095 return & rmg -> rmg_res_buckets [idx ];
20852096}
@@ -2196,7 +2207,7 @@ migrate_res_release(struct migrate_pool_tls *tls, int res_type, long units)
21962207 res -> res_data .mem_hulk = 0 ;
21972208 }
21982209
2199- if (res -> res_waiters > 0 )
2210+ if (res -> res_waiters > 0 && res -> res_limit > res -> res_used )
22002211 migrate_res_wakeup (res , res -> res_limit - res -> res_used );
22012212
22022213 if (!migr_res_is_private (res ))
@@ -3646,8 +3657,10 @@ migrate_object(daos_unit_oid_t oid, daos_epoch_t eph, daos_epoch_t punched_eph,
36463657
36473658 D_ASSERT (tgt_idx == dss_get_module_info ()-> dmi_tgt_id );
36483659 rc = dss_ult_create (migrate_obj_ult , obj_arg , DSS_XS_SELF , 0 , MIGRATE_STACK_SIZE , NULL );
3649- if (rc )
3660+ if (rc ) {
3661+ migrate_res_release (cont_arg -> pool_tls , MIGR_OBJ , obj_arg -> ioa_fanout );
36503662 goto free ;
3663+ }
36513664
36523665 val .epoch = eph ;
36533666 val .shard = shard ;
@@ -4848,6 +4861,7 @@ migr_rmg_fini(int type)
48484861
48494862 for (i = 0 ; i < rmg -> rmg_bkt_nr ; i ++ )
48504863 migr_res_fini (& rmg -> rmg_res_buckets [i ]);
4864+ D_FREE (rmg -> rmg_res_buckets );
48514865 memset (rmg , 0 , sizeof (* rmg ));
48524866}
48534867
0 commit comments