]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
erasure-code/jerasure: Fix thread safety in plugin init 67498/head
authorJamie Pryde <jamiepry@uk.ibm.com>
Tue, 24 Feb 2026 22:19:59 +0000 (22:19 +0000)
committerJamie Pryde <jamiepry@uk.ibm.com>
Tue, 24 Feb 2026 22:19:59 +0000 (22:19 +0000)
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 <jamiepry@uk.ibm.com>
src/erasure-code/jerasure/ErasureCodeJerasure.cc
src/erasure-code/jerasure/ErasureCodeJerasure.h

index 9444b0d05813c9895daa255b37b1643eb3e32bbe..53136fede47f5bdcf7e3ab323959d19e79bbbf52 100644 (file)
@@ -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);
index 783fb84e364cca4fa28593031932f0f64e9c375e..7e2b0d60634c552de7a041b4d6a877ed1ca48eed 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <string_view>
 
+#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: