From: Jamie Pryde Date: Tue, 24 Feb 2026 22:19:59 +0000 (+0000) Subject: erasure-code/jerasure: Fix thread safety in plugin init X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8b47e8e8360aff613982aa74597b452e7465cb50;p=ceph.git erasure-code/jerasure: Fix thread safety in plugin init The Jerasure function cauchy_good_general_coding_matrix() has a race condition where it uses a global variable cbest_init without proper synchronization. When multiple threads initialize PGs simultaneously, they can race on this initialization, causing one thread to read from cbest_all before it's fully initialized, resulting in a segmentation fault. This commit adds a static mutex to serialize the prepare() calls during init for all Jerasure techniques. Fixes: https://tracker.ceph.com/issues/73246 Signed-off-by: Jamie Pryde --- diff --git a/src/erasure-code/jerasure/ErasureCodeJerasure.cc b/src/erasure-code/jerasure/ErasureCodeJerasure.cc index 9444b0d05813..53136fede47f 100644 --- a/src/erasure-code/jerasure/ErasureCodeJerasure.cc +++ b/src/erasure-code/jerasure/ErasureCodeJerasure.cc @@ -42,6 +42,10 @@ using std::set; using ceph::bufferlist; using ceph::ErasureCodeProfile; +ceph::mutex ErasureCodeJerasure::jerasure_init_mutex = + ceph::make_mutex("ErasureCodeJerasure::jerasure_init_mutex"); + + static ostream& _prefix(std::ostream* _dout) { return *_dout << "ErasureCodeJerasure: "; @@ -426,6 +430,7 @@ int ErasureCodeJerasureReedSolomonVandermonde::parse(ErasureCodeProfile &profile void ErasureCodeJerasureReedSolomonVandermonde::prepare() { + std::lock_guard lock(jerasure_init_mutex); matrix = reed_sol_vandermonde_coding_matrix(k, m, w); } @@ -484,6 +489,7 @@ int ErasureCodeJerasureReedSolomonRAID6::parse(ErasureCodeProfile &profile, void ErasureCodeJerasureReedSolomonRAID6::prepare() { + std::lock_guard lock(jerasure_init_mutex); matrix = reed_sol_r6_coding_matrix(k, w); } @@ -561,6 +567,7 @@ ErasureCodeJerasureCauchy::~ErasureCodeJerasureCauchy() // void ErasureCodeJerasureCauchyOrig::prepare() { + std::lock_guard lock(jerasure_init_mutex); int *matrix = cauchy_original_coding_matrix(k, m, w); prepare_schedule(matrix); free(matrix); @@ -571,6 +578,7 @@ void ErasureCodeJerasureCauchyOrig::prepare() // void ErasureCodeJerasureCauchyGood::prepare() { + std::lock_guard lock(jerasure_init_mutex); int *matrix = cauchy_good_general_coding_matrix(k, m, w); prepare_schedule(matrix); free(matrix); @@ -698,6 +706,7 @@ int ErasureCodeJerasureLiberation::parse(ErasureCodeProfile &profile, void ErasureCodeJerasureLiberation::prepare() { + std::lock_guard lock(jerasure_init_mutex); bitmatrix = liberation_coding_bitmatrix(k, w); schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); simple_schedule = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix); @@ -723,6 +732,7 @@ bool ErasureCodeJerasureBlaumRoth::check_w(ostream *ss) const void ErasureCodeJerasureBlaumRoth::prepare() { + std::lock_guard lock(jerasure_init_mutex); bitmatrix = blaum_roth_coding_bitmatrix(k, w); schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); simple_schedule = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix); @@ -761,6 +771,7 @@ int ErasureCodeJerasureLiber8tion::parse(ErasureCodeProfile &profile, void ErasureCodeJerasureLiber8tion::prepare() { + std::lock_guard lock(jerasure_init_mutex); bitmatrix = liber8tion_coding_bitmatrix(k); schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix); simple_schedule = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix); diff --git a/src/erasure-code/jerasure/ErasureCodeJerasure.h b/src/erasure-code/jerasure/ErasureCodeJerasure.h index 783fb84e364c..7e2b0d60634c 100644 --- a/src/erasure-code/jerasure/ErasureCodeJerasure.h +++ b/src/erasure-code/jerasure/ErasureCodeJerasure.h @@ -21,6 +21,7 @@ #include +#include "common/ceph_mutex.h" #include "erasure-code/ErasureCode.h" using namespace std::literals; @@ -124,6 +125,12 @@ public: protected: virtual int parse(ceph::ErasureCodeProfile &profile, std::ostream *ss); + + // The Jerasure library has thread safety issues in functions + // like cauchy_good_general_coding_matrix() which use global variables + // without proper synchronization. This mutex serializes all prepare() + // calls to prevent race conditions during initialization. + static ceph::mutex jerasure_init_mutex; }; class ErasureCodeJerasureReedSolomonVandermonde : public ErasureCodeJerasure { public: