All writes in EC are asynchronous (even if they are only updating metadata), so Cls reads in EC must use the RWEXCL lock to eliminate the possibility of race conditions.
This resolves failures with Cls queue tests on EC pools where read operations were observed overtaking in-flight writes.
Fixes: https://tracker.ceph.com/issues/74531
Signed-off-by: Matty Williams <Matty.Williams@ibm.com>
bool check_rmw(int flag) const { return op_info.check_rmw(flag); }
bool may_read() const { return op_info.may_read(); }
bool may_read_data() const { return op_info.may_read_data(); }
+ bool may_read_data_for_ec() const { return op_info.may_read_data_for_ec(); }
bool may_write() const { return op_info.may_write(); }
bool may_cache() const { return op_info.may_cache(); }
bool rwordered_forced() const { return op_info.rwordered_forced(); }
* to get the second.
*/
if (write_ordered && ctx->op->may_read()) {
- if (ctx->op->may_read_data()) {
+ // In EC, reads can overtake writes unless the RWEXCL lock is held
+ if (ctx->op->may_read_data() ||
+ (pool.info.is_erasure() && ctx->op->may_read_data_for_ec())) {
ctx->lock_type = RWState::RWEXCL;
} else {
ctx->lock_type = RWState::RWWRITE;
return check_rmw(CEPH_OSD_RMW_FLAG_READ_DATA);
}
+bool OpInfo::may_read_data_for_ec() const
+{
+ return check_rmw(CEPH_OSD_RMW_FLAG_CLASS_READ_DATA);
+}
+
void OpInfo::set_rmw_flags(int flags) {
rmw_flags |= flags;
}
void OpInfo::set_read() { set_rmw_flags(CEPH_OSD_RMW_FLAG_READ); }
void OpInfo::set_write() { set_rmw_flags(CEPH_OSD_RMW_FLAG_WRITE); }
-void OpInfo::set_class_read() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CLASS_READ); }
+void OpInfo::set_class_read(const bool is_erasure) {
+ int flags = CEPH_OSD_RMW_FLAG_CLASS_READ;
+ if (is_erasure) {
+ flags |= CEPH_OSD_RMW_FLAG_CLASS_READ_DATA;
+ }
+ set_rmw_flags(flags);
+}
void OpInfo::set_class_write() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CLASS_WRITE); }
void OpInfo::set_pg_op() { set_rmw_flags(CEPH_OSD_RMW_FLAG_PGOP); }
void OpInfo::set_cache() { set_rmw_flags(CEPH_OSD_RMW_FLAG_CACHE); }
is_write = flags & CLS_METHOD_WR;
bool is_promote = flags & CLS_METHOD_PROMOTE;
- if (is_read)
- set_class_read();
+ if (is_read) {
+ const bool is_erasure = pool && pool->is_erasure();
+ set_class_read(is_erasure);
+ }
if (is_write)
set_class_write();
if (is_promote)
bool check_rmw(int flag) const ;
bool may_read() const;
bool may_read_data() const;
+ bool may_read_data_for_ec() const;
bool may_write() const;
bool may_cache() const;
bool rwordered_forced() const;
void set_read();
void set_write();
void set_cache();
- void set_class_read();
+ void set_class_read(bool is_erasure);
void set_class_write();
void set_pg_op();
void set_promote();
CEPH_OSD_RMW_FLAG_RETURNVEC = (1 << 11),
CEPH_OSD_RMW_FLAG_READ_DATA = (1 << 12),
CEPH_OSD_RMW_FLAG_EC_DIRECT_READ = (1 << 13),
+ CEPH_OSD_RMW_FLAG_EC_SYNC_READ = (1 << 14),
+ CEPH_OSD_RMW_FLAG_CLASS_READ_DATA = (1 << 15),
};