From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 78C703AA1B6 for ; Sun, 16 Aug 2026 17:00:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786899605; cv=none; b=IUTlnJBJqhTf9IVsxCy7QHRrtizeSJXOdUkTbkweDEwnZlTRDqsdSvv/KMGB6LF3LCaqFzqqWpiQbVjH9sqxlDRkMRSAW+4jyCQHI+jG766cZw5xSnf4f/Qs2u7cKnwuZa2DGVBETSgpZwSgxMR2eeEJeXq/Jj8Q5Iz6h+BYwDc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786899605; c=relaxed/simple; bh=Cf1L0TSCjenT1W+tNxNkfUMwJYdG+o8nYga8DrBBhk8=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=K81Hb9Oro8sEJLiUA2iFJ4JDyhMcPnQwoJrAuzJ64lchEBT8yJEBiTiOVMeh6rHqRPgf05OFi7KLaRC9TAH2xLeCD6liYMNQkqfW3CA8h0Bzsgur72QohCzqhGVsyzARyQZb2weEjb2yP+Rm2bA5S0k5hOVXVFHuN6VJVaA4Yc4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=a9lVMXLH; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="a9lVMXLH" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2ce87c7e3bbso33693765ad.1 for ; Sun, 16 Aug 2026 10:00:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786899604; x=1787504404; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=bnrji67FLS0+3KHmX8HTFOo33nEr+usZlyNhp+PZ+bc=; b=a9lVMXLHaiaRwHrPKDkEUVMIc9W+yCp6/qedWwOTvLnVEsjsQjO7+K8BJq5jGPq8Hf xYGblae1LllOAkHZn13ZcadqVUiiIaMU3P3bCFUW6rC7LeoY+LwlEUrVuzVVxgsJy5Qz nrf6aAKVA4bJiIHArPB+n41UUov8FNBr/mwGm/0QHn3ziOO2G+uVxC+DmyCzpd3UoOSp zFRfU/m3On/5UDrAAgHBwTr/R3X2GFd8HSjxBnsSaiogMTKiAE6Neo6BU02lr0py/wkB 2yT2hKxBQDwFp2KL32pF9epSmcJCdOENpFzHCDzZvX3rGQdGgZr9HKQDogWtDPQeC6XO /AFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786899604; x=1787504404; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=bnrji67FLS0+3KHmX8HTFOo33nEr+usZlyNhp+PZ+bc=; b=WrYRZnuz/m93ROSaxCB5RudhfUyjrMxRXN+l7eGnJbl3DdU2d+Jo5MQcqpuMnx4Z14 htt2J/lNkMYjuO2wOaJbNR1p5WskbjNY5enPVYFYHTya5OiED3qwUFY/d4db3hNIBk+V O7M4vLsqtHRE+3Gxo8iGWyu75kJdR5C8o1irK0LywXEEzq1yekbkKl8qGamwYaMq+Ev2 mbnB6Ybj3HX/xjC7R1NwapQbwi/BoMtsCxszA3yVI3VzlRg65TwtdklnR237km3Ty5w7 qS5aUn7beE62yLLFM1IkMzxWGAEa0jgDDFk2HRc4vTOsBaXICJuYGUUS+f8H+Iaweun7 Ej2Q== X-Forwarded-Encrypted: i=1; AHgh+RrD7uD4qElR0RK9O89ZcPwTo/mIFtMNDZVZ3o+Z70uzq7U7Tz7QVN56zzR95amHR+D7v2WgXLkJXpM11as=@vger.kernel.org X-Gm-Message-State: AOJu0YwujMQ+ZdVknHyD3VmRhW241Sks3rCqIWJbEojKJ9C6YDMEM99j KEFgDTkyNXNjtNt8LZNoazSFNBEMBNrCPz2PCqrpOYCVzyt1BlhLrnQR X-Gm-Gg: AR+sD11Zw4yHPcJOnwJp9foB5ojZ5eXLPsLgxj4JrGL170tXpzr1L5jS2CJWUAbQ/sJ vJBEnL88R0qGCWwn9MA15b32NpTJmO7wAzLPyT3ywanEuXGf9PJ4DogQyJvEGN211lcSnYkW0Tw P/xyN/HTUYGYnyYyAQpRb4VADJjuGTAvp8vXxUlvHxPzT1EPvNZI6PBm86X224FFBlcI0RHk5Ky A1Z3NpDwtcu66rJn6dIOkyMdRo1VCXmqYe6jFCNf3vLSi6ui1wQxhHzxh0HpBzgjZHOZTfGk5M9 mV3LQQupaA6dbYaPxgfqKOhlOlOxv1aeKDLQHMhU4JLObDgqr6fHBDLgY3/zooC9ub2OYyvmibx u+dcGRenneD4GyxaNOqlMMClPaHB+F7WdI3EL/OpKso201Xzjg5c/tpK93GmzJ5m5er7tfHclCP +pAvmHrlhqz2+38pDFGlw5Mi2TNIdNtWwcV7GWuxsC54jpqv8pHTB0wxr9Ej1xBsyL/R/2yJeAk Gcrn7VdJ6tFyd/k2HE+WLmnZgQ2AB14 X-Received: by 2002:a17:90b:1b45:b0:380:71eb:4014 with SMTP id 98e67ed59e1d1-3933b944a7cmr19106351a91.15.1786899603542; Sun, 16 Aug 2026 10:00:03 -0700 (PDT) Received: from localhost.localdomain ([240a:4280:4800:1470:95d0:2f3e:656d:65de]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39531e62a7bsm1938648a91.6.2026.08.16.09.59.58 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 16 Aug 2026 10:00:02 -0700 (PDT) From: Liu Zhenlong To: haris.iqbal@ionos.com, jinpu.wang@ionos.com Cc: Liu Zhenlong , jgg@ziepe.ca, leon@kernel.org, linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] RDMA/rtrs-clt: use find_next_zero_bit() for permit allocation Date: Mon, 17 Aug 2026 00:59:16 +0800 Message-ID: <20260816165935.90523-1-dragonliu2018@gmail.com> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit __rtrs_get_permit() allocates a free permit from a bitmap under lockless contention: it scans with find_first_zero_bit() and claims the bit with test_and_set_bit_lock(), restarting the whole scan when it loses the race. Each retry rewinds to bit 0 and re-walks every already-set low bit before reaching the free region again. Under high queue depth - the RTRS/RNBD data path - the low part of permits_map is densely set, so a lost race wastes a scan proportional to the number of in-use permits on every retry. Use find_next_zero_bit(), resuming from the last position, so a lost race continues scanning from where it left off instead of from the beginning. When the scan reaches the end, wrap to the beginning to exhaust the map, so a permit freed below the cursor is still found and NULL is returned only when the map is actually full, matching the original behavior. The scan remains non-atomic, so the test_and_set_bit_lock() retry is still required and the race handling is unchanged. A userspace model of the bitmap-allocation algorithm (not the kernel find_*_bit primitives) quantifies the mechanism: with qdepth=512 and 14 threads holding ~98% of the bits set, a lost race in the baseline re-scans the densely-set low region, traversing ~1.3k bit-positions per allocation, while the patched version resumes and traverses ~260. The benefit is contention- and density-dependent: under low contention (sparse map) the two are equivalent, and the wrap adds a small amount of code over the single-scan baseline. End-to-end RNBD/fio throughput was not measured (no RDMA hardware available); the model isolates the allocation mechanism, not the full IO path. Compile-tested: arm64 defconfig + INFINIBAND_RTRS_CLIENT=m, rtrs-clt.o Assisted-by: Claude:claude-opus-5 Signed-off-by: Liu Zhenlong --- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index d34d7e5f34d6..a1df90243c41 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -70,19 +70,24 @@ __rtrs_get_permit(struct rtrs_clt_sess *clt, enum rtrs_clt_con_type con_type) { size_t max_depth = clt->queue_depth; struct rtrs_permit *permit; - int bit; + unsigned long bit = 0; /* - * Adapted from null_blk get_tag(). Callers from different cpus may - * grab the same bit, since find_first_zero_bit is not atomic. - * But then the test_and_set_bit_lock will fail for all the - * callers but one, so that they will loop again. - * This way an explicit spinlock is not required. + * Callers from different CPUs may grab the same bit, since the bitmap + * scan is not atomic. But then the test_and_set_bit_lock() will fail + * for all the callers but one, so that they loop again. This way an + * explicit spinlock is not required. find_next_zero_bit() resumes + * from the last position so that a lost race does not rescan the + * already-set low bits; if it reaches the end, wrap to the beginning + * to exhaust the map and still find a permit freed below the cursor. */ do { - bit = find_first_zero_bit(clt->permits_map, max_depth); - if (bit >= max_depth) - return NULL; + bit = find_next_zero_bit(clt->permits_map, max_depth, bit); + if (bit >= max_depth) { + bit = find_first_zero_bit(clt->permits_map, max_depth); + if (bit >= max_depth) + return NULL; + } } while (test_and_set_bit_lock(bit, clt->permits_map)); permit = get_permit(clt, bit); -- 2.55.0