]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: decode_concat() always honors want_to_read
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Sun, 9 Jun 2024 08:28:42 +0000 (08:28 +0000)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Thu, 20 Jun 2024 20:37:57 +0000 (20:37 +0000)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/erasure-code/ErasureCode.cc
src/test/erasure-code/TestErasureCodeExample.cc
src/test/erasure-code/TestErasureCodeJerasure.cc

index ef92ea7219d89d550958f6869883715f48d37f68..b27273c172fd61527ac0f768a3b6aca10053ea6c 100644 (file)
@@ -356,7 +356,13 @@ int ErasureCode::decode_concat(const set<int>& want_to_read,
   int r = _decode(want_to_read, chunks, &decoded_map);
   if (r == 0) {
     for (unsigned int i = 0; i < get_data_chunk_count(); i++) {
-      if (decoded_map.contains(chunk_index(i))) {
+      // XXX: the ErasureCodeInterface allows `decode()` to return
+      // *at least* `want_to_read chunks`; that is, they may more.
+      // Some implementations are consistently exact but jerasure
+      // is quirky: it outputs more only when deailing with degraded.
+      // The check below uniforms the behavior.
+      if (want_to_read.contains(chunk_index(i)) &&
+         decoded_map.contains(chunk_index(i))) {
         decoded->claim_append(decoded_map[chunk_index(i)]);
       }
     }
index ce89cba33724583067e26ec33ef29a13c17c81b7..9e67b9c9ca70e7e0059a675eb6cdd3adf407851f 100644 (file)
@@ -194,16 +194,29 @@ TEST(ErasureCodeExample, decode)
   bufferlist out;
   EXPECT_EQ(0, example.decode_concat(encoded, &out));
   bufferlist usable;
+  EXPECT_EQ(2u*encoded[0].length(), out.length());
   usable.substr_of(out, 0, in.length());
   EXPECT_TRUE(usable == in);
 
   // partial chunk decode
-  map<int, bufferlist> partial_decode;
-  partial_decode[0] = encoded[0];
+  map<int, bufferlist> partial_decode = encoded;
   set<int> partial_want_to_read{want_to_encode, want_to_encode+1};
+  EXPECT_EQ(1u, partial_want_to_read.size());
+  out.clear();
   EXPECT_EQ(0, example.decode_concat(partial_want_to_read,
                                     partial_decode,
                                     &out));
+  EXPECT_EQ(out.length(), encoded[0].length());
+
+  // partial degraded chunk decode
+  partial_decode = encoded;
+  partial_decode.erase(0);
+  EXPECT_EQ(1, partial_want_to_read.size());
+  out.clear();
+  EXPECT_EQ(0, example.decode_concat(partial_want_to_read,
+                                    partial_decode,
+                                    &out));
+  EXPECT_EQ(out.length(), encoded[0].length());
 
   // cannot recover
   map<int, bufferlist> degraded;  
index 835f3c7b6c8f8d15b945328d95e9d7b56cd351a5..3946892c8aa633a3b515b4280741d1c600b4014b 100644 (file)
@@ -127,6 +127,33 @@ TYPED_TEST(ErasureCodeTest, encode_decode)
       EXPECT_EQ(0, memcmp(decoded[1].c_str(), in.c_str() + length,
                          in.length() - length));
     }
+
+    // partial decode with the exact-sized decode_concat()
+    {
+      map<int, bufferlist> partial_decode = encoded;
+      // we have everything but want only the first chunk
+      set<int> partial_want_to_read = { 0 };
+      EXPECT_EQ(1u, partial_want_to_read.size());
+      bufferlist out;
+      EXPECT_EQ(0, jerasure.decode_concat(partial_want_to_read,
+                                         partial_decode,
+                                         &out));
+      EXPECT_EQ(out.length(), partial_decode[0].length());
+    }
+
+    // partial degraded decode with the exact-sized decode_concat()
+    {
+      map<int, bufferlist> partial_decode = encoded;
+      // we have everything but what we really want
+      partial_decode.erase(0);
+      set<int> partial_want_to_read = { 0 };
+      EXPECT_EQ(1u, partial_want_to_read.size());
+      bufferlist out;
+      EXPECT_EQ(0, jerasure.decode_concat(partial_want_to_read,
+                                         partial_decode,
+                                         &out));
+      EXPECT_EQ(out.length(), encoded[0].length());
+    }
   }
 }