From 81daa87f8b3ac25de22d4854313507a1258dbe6d Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sun, 14 Jun 2026 18:52:54 -0700 Subject: [PATCH] rdma-engine: ranged RDMA READ (offset+size) in rdma-client Match the real read API shape (file_id + offset + size): rdma-client takes optional [offset] [size] and RDMA-READs only that sub-range from the remote MR (remote_addr + offset). Verified over rxe0: reading [3 MiB, 4 MiB) of an 8 MiB target file yields bytes whose md5 matches the source slice. --- .../rdma-engine/src/bin/rdma_client.rs | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/seaweedfs-rdma-sidecar/rdma-engine/src/bin/rdma_client.rs b/seaweedfs-rdma-sidecar/rdma-engine/src/bin/rdma_client.rs index ce70ac506..6cb2efd94 100644 --- a/seaweedfs-rdma-sidecar/rdma-engine/src/bin/rdma_client.rs +++ b/seaweedfs-rdma-sidecar/rdma-engine/src/bin/rdma_client.rs @@ -3,7 +3,10 @@ //! space), and write it out. md5 of the output vs the target's source file //! proves a real cross-process RDMA read of real data. //! -//! cargo run --features real-rdma --bin rdma-client -- +//! cargo run --features real-rdma --bin rdma-client -- [offset] [size] +//! +//! With [offset]/[size] it RDMA-READs only that byte range (the real read API +//! shape: file_id + offset + size); without them it reads the whole MR. use std::fs; @@ -12,12 +15,13 @@ use rdma_engine::rdma_real::RealRdmaContext; fn main() { let args: Vec = std::env::args().collect(); if args.len() < 4 { - eprintln!("usage: rdma-client "); + eprintln!("usage: rdma-client [offset] [size]"); std::process::exit(2); } let ip = args[1].clone(); let port: u16 = args[2].parse().expect("port"); let out = &args[3]; + let offset: u64 = args.get(4).and_then(|s| s.parse().ok()).unwrap_or(0); let (ctx, raddr, rkey, rlen) = match RealRdmaContext::connect(&ip, port) { Ok(v) => v, @@ -26,11 +30,22 @@ fn main() { std::process::exit(1); } }; - eprintln!("client: connected to {ip}:{port}, remote MR len={rlen} rkey=0x{rkey:x}"); + // Default to the rest of the MR from `offset`. + let size: usize = args + .get(5) + .and_then(|s| s.parse().ok()) + .unwrap_or(rlen - offset.min(rlen as u64) as usize); + eprintln!( + "client: connected to {ip}:{port}, remote MR len={rlen} rkey=0x{rkey:x}; reading [{offset}, {})", + offset as usize + size + ); + assert!(offset as usize + size <= rlen, "range exceeds remote MR"); - let mut dest = vec![0u8; rlen]; + let mut dest = vec![0u8; size]; let (_mi, mr) = ctx.register_memory(&mut dest).expect("register dest"); - ctx.post_read(&mut dest, mr, raddr, rkey, 1).expect("post_read"); + // RDMA-READ the sub-range: remote source is the MR base + offset. + ctx.post_read(&mut dest, mr, raddr + offset, rkey, 1) + .expect("post_read"); let wc = ctx.poll_completion().expect("poll completion"); ctx.finish(); eprintln!(