Skip to content

Commit a3441a7

Browse files
committed
librbd: diff-iterate shouldn't crash on an empty byte range
Commit 0b5ba5f ("librbd/object_map: add support for ranged diff-iterate") introduced a regression for the case when whole_object parameter is set to true. Despite DiffRequest being called into and another DiffIterate potentially being spawned recursively, an empty byte range previously happened to make it. Bail on an empty byte range early just like we have always done on an empty snap id range (i.e. when start and end versions are the same). Fixes: https://tracker.ceph.com/issues/66418 Signed-off-by: Ilya Dryomov <[email protected]>
1 parent 6b5f008 commit a3441a7

File tree

2 files changed

+59
-9
lines changed

2 files changed

+59
-9
lines changed

src/librbd/api/DiffIterate.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,13 @@ int DiffIterate<I>::execute() {
312312
if (from_snap_id == CEPH_NOSNAP) {
313313
return -ENOENT;
314314
}
315-
if (from_snap_id == end_snap_id) {
315+
if (from_snap_id > end_snap_id) {
316+
return -EINVAL;
317+
}
318+
if (from_snap_id == end_snap_id || m_length == 0) {
316319
// no diff.
317320
return 0;
318321
}
319-
if (from_snap_id >= end_snap_id) {
320-
return -EINVAL;
321-
}
322322

323323
int r;
324324
bool fast_diff_enabled = false;

src/test/librbd/test_librbd.cc

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8529,23 +8529,59 @@ TYPED_TEST(DiffIterateTest, DiffIterateUnalignedSmall)
85298529
{
85308530
librbd::RBD rbd;
85318531
librbd::Image image;
8532-
int order = 0;
8532+
int order = 22;
85338533
std::string name = this->get_temp_image_name();
8534-
ssize_t size = 10 << 20;
8534+
ssize_t data_end = 8 << 20;
85358535

8536-
ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order));
8536+
ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(),
8537+
data_end + (2 << 20), &order));
85378538
ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
85388539

85398540
ceph::bufferlist bl;
8540-
bl.append(std::string(size, '1'));
8541-
ASSERT_EQ(size, image.write(0, size, bl));
8541+
bl.append(std::string(data_end, '1'));
8542+
ASSERT_EQ(data_end, image.write(0, data_end, bl));
85428543

85438544
std::vector<diff_extent> extents;
8545+
ASSERT_EQ(0, image.diff_iterate2(NULL, 0, 0, true,
8546+
this->whole_object, vector_iterate_cb,
8547+
&extents));
8548+
ASSERT_EQ(0u, extents.size());
8549+
85448550
ASSERT_EQ(0, image.diff_iterate2(NULL, 5000005, 1234, true,
85458551
this->whole_object, vector_iterate_cb,
85468552
&extents));
85478553
ASSERT_EQ(1u, extents.size());
85488554
ASSERT_EQ(diff_extent(5000005, 1234, true, 0), extents[0]);
8555+
extents.clear();
8556+
8557+
ASSERT_EQ(0, image.diff_iterate2(NULL, data_end - 1, 0, true,
8558+
this->whole_object, vector_iterate_cb,
8559+
&extents));
8560+
ASSERT_EQ(0u, extents.size());
8561+
8562+
ASSERT_EQ(0, image.diff_iterate2(NULL, data_end - 1, 1, true,
8563+
this->whole_object, vector_iterate_cb,
8564+
&extents));
8565+
ASSERT_EQ(1u, extents.size());
8566+
ASSERT_EQ(diff_extent(data_end - 1, 1, true, 0), extents[0]);
8567+
extents.clear();
8568+
8569+
ASSERT_EQ(0, image.diff_iterate2(NULL, data_end - 1, 2, true,
8570+
this->whole_object, vector_iterate_cb,
8571+
&extents));
8572+
ASSERT_EQ(1u, extents.size());
8573+
ASSERT_EQ(diff_extent(data_end - 1, 1, true, 0), extents[0]);
8574+
extents.clear();
8575+
8576+
ASSERT_EQ(0, image.diff_iterate2(NULL, data_end, 0, true,
8577+
this->whole_object, vector_iterate_cb,
8578+
&extents));
8579+
ASSERT_EQ(0u, extents.size());
8580+
8581+
ASSERT_EQ(0, image.diff_iterate2(NULL, data_end, 1, true,
8582+
this->whole_object, vector_iterate_cb,
8583+
&extents));
8584+
ASSERT_EQ(0u, extents.size());
85498585

85508586
ASSERT_PASSED(this->validate_object_map, image);
85518587
}
@@ -8580,6 +8616,20 @@ TYPED_TEST(DiffIterateTest, DiffIterateUnaligned)
85808616
ASSERT_EQ(diff_extent(8376263, 12345, true, 0), extents[0]);
85818617
ASSERT_EQ(diff_extent(8388608, 4194304, true, 0), extents[1]);
85828618
ASSERT_EQ(diff_extent(12582912, 54321, true, 0), extents[2]);
8619+
extents.clear();
8620+
8621+
// length is clipped up to end
8622+
ASSERT_EQ(0, image.diff_iterate2(NULL, size - 1, size, true,
8623+
this->whole_object, vector_iterate_cb,
8624+
&extents));
8625+
ASSERT_EQ(1u, extents.size());
8626+
ASSERT_EQ(diff_extent(size - 1, 1, true, 0), extents[0]);
8627+
extents.clear();
8628+
8629+
// offset past end
8630+
ASSERT_EQ(-EINVAL, image.diff_iterate2(NULL, size, size, true,
8631+
this->whole_object,
8632+
vector_iterate_cb, &extents));
85838633

85848634
ASSERT_PASSED(this->validate_object_map, image);
85858635
}

0 commit comments

Comments
 (0)