From: Xiubo Li <xiubo.li@clyso.com>
ceph_osdc_alloc_request() ORs the mount option's read_from_replica
flag into r_flags for every request, writes included. The flag is
meant for reads: calc_target() skips the replica choice for any
request that has CEPH_OSD_FLAG_WRITE, and the OSDs only know
BALANCE_READS on read ops. Sending it on writes is at best ignored;
with read_from_replica=balance a buffered write that fell back to
ceph_sync_write() after losing BUFFER to a revoke failed with -EIO,
while the same run without the option works fine.
Gate the flag on CEPH_OSD_FLAG_READ.
Fixes: 22d2cfdffa5b ("libceph: move away from global osd_req_flags")
Cc: stable@vger.kernel.org
Signed-off-by: Xiubo Li <xiubo.li@clyso.com>
---
net/ceph/osd_client.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index f68918fc27f9..a5fc5de2c2b5 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1109,7 +1109,9 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
req->r_base_oloc.pool = layout->pool_id;
req->r_base_oloc.pool_ns = ceph_try_get_string(layout->pool_ns);
ceph_oid_printf(&req->r_base_oid, "%llx.%08llx", vino.ino, objnum);
- req->r_flags = flags | osdc->client->options->read_from_replica;
+ req->r_flags = flags;
+ if (flags & CEPH_OSD_FLAG_READ)
+ req->r_flags |= osdc->client->options->read_from_replica;
req->r_snapid = vino.snap;
if (flags & CEPH_OSD_FLAG_WRITE)
---
base-commit: 6b039a71d37a39bb90a64c4e271f90ee0588ac4a
change-id: 20260903-b4-read-from-replica-2333eabb2e83
Best regards,
--
Xiubo Li <xiubo.li@clyso.com>