@@ -1096,6 +1096,20 @@ record_t Cache::prepare_record(
10961096 if (!i->is_exist_mutation_pending ()) {
10971097 DEBUGT (" commit replace extent ... -- {}, prior={}" ,
10981098 t, *i, *i->prior_instance );
1099+ // If inplace rewrite occurs during mutation, prev->version will
1100+ // be zero. Although this results in the version mismatch here, we can
1101+ // correct this by changing version to 1. This is because the inplace rewrite
1102+ // does not introduce any actual modification that could negatively
1103+ // impact system reliability
1104+ if (i->prior_instance ->version == 0 && i->version > 1 ) {
1105+ assert (can_inplace_rewrite (i->get_type ()));
1106+ assert (can_inplace_rewrite (i->prior_instance ->get_type ()));
1107+ assert (i->prior_instance ->dirty_from_or_retired_at == JOURNAL_SEQ_MIN);
1108+ assert (i->prior_instance ->state == CachedExtent::extent_state_t ::CLEAN);
1109+ assert (i->prior_instance ->get_paddr ().get_addr_type () ==
1110+ paddr_types_t ::RANDOM_BLOCK);
1111+ i->version = 1 ;
1112+ }
10991113 // extent with EXIST_MUTATION_PENDING doesn't have
11001114 // prior_instance field so skip these extents.
11011115 // the existing extents should be added into Cache
@@ -1261,6 +1275,24 @@ record_t Cache::prepare_record(
12611275 }
12621276 }
12631277
1278+ for (auto &i: t.written_inplace_ool_block_list ) {
1279+ if (!i->is_valid ()) {
1280+ continue ;
1281+ }
1282+ assert (i->state == CachedExtent::extent_state_t ::DIRTY);
1283+ assert (i->version > 0 );
1284+ remove_from_dirty (i);
1285+ // set the version to zero because the extent state is now clean
1286+ // in order to handle this transparently
1287+ i->version = 0 ;
1288+ i->dirty_from_or_retired_at = JOURNAL_SEQ_MIN;
1289+ i->state = CachedExtent::extent_state_t ::CLEAN;
1290+ assert (i->is_logical ());
1291+ i->clear_modified_region ();
1292+ touch_extent (*i);
1293+ DEBUGT (" inplace rewrite ool block is commmitted -- {}" , t, *i);
1294+ }
1295+
12641296 for (auto &i: t.existing_block_list ) {
12651297 if (i->is_valid ()) {
12661298 alloc_delta.alloc_blk_ranges .emplace_back (
@@ -1330,7 +1362,8 @@ record_t Cache::prepare_record(
13301362 t.num_allocated_invalid_extents );
13311363
13321364 auto & ool_stats = t.get_ool_write_stats ();
1333- ceph_assert (ool_stats.extents .num == t.written_ool_block_list .size ());
1365+ ceph_assert (ool_stats.extents .num == t.written_ool_block_list .size () +
1366+ t.written_inplace_ool_block_list .size ());
13341367
13351368 if (record.is_empty ()) {
13361369 SUBINFOT (seastore_t ,
@@ -1699,22 +1732,25 @@ Cache::replay_delta(
16991732 segment_seq_printer_t {delta_paddr_segment_seq},
17001733 delta_paddr_segment_type,
17011734 delta);
1702- return replay_delta_ertr::make_ready_future<bool >(false );
1735+ return replay_delta_ertr::make_ready_future<std::pair<bool , CachedExtentRef>>(
1736+ std::make_pair (false , nullptr ));
17031737 }
17041738 }
17051739 }
17061740
17071741 if (delta.type == extent_types_t ::JOURNAL_TAIL) {
17081742 // this delta should have been dealt with during segment cleaner mounting
1709- return replay_delta_ertr::make_ready_future<bool >(false );
1743+ return replay_delta_ertr::make_ready_future<std::pair<bool , CachedExtentRef>>(
1744+ std::make_pair (false , nullptr ));
17101745 }
17111746
17121747 // replay alloc
17131748 if (delta.type == extent_types_t ::ALLOC_INFO) {
17141749 if (journal_seq < alloc_tail) {
17151750 DEBUG (" journal_seq {} < alloc_tail {}, don't replay {}" ,
17161751 journal_seq, alloc_tail, delta);
1717- return replay_delta_ertr::make_ready_future<bool >(false );
1752+ return replay_delta_ertr::make_ready_future<std::pair<bool , CachedExtentRef>>(
1753+ std::make_pair (false , nullptr ));
17181754 }
17191755
17201756 alloc_delta_t alloc_delta;
@@ -1738,14 +1774,16 @@ Cache::replay_delta(
17381774 if (!backref_list.empty ()) {
17391775 backref_batch_update (std::move (backref_list), journal_seq);
17401776 }
1741- return replay_delta_ertr::make_ready_future<bool >(true );
1777+ return replay_delta_ertr::make_ready_future<std::pair<bool , CachedExtentRef>>(
1778+ std::make_pair (true , nullptr ));
17421779 }
17431780
17441781 // replay dirty
17451782 if (journal_seq < dirty_tail) {
17461783 DEBUG (" journal_seq {} < dirty_tail {}, don't replay {}" ,
17471784 journal_seq, dirty_tail, delta);
1748- return replay_delta_ertr::make_ready_future<bool >(false );
1785+ return replay_delta_ertr::make_ready_future<std::pair<bool , CachedExtentRef>>(
1786+ std::make_pair (false , nullptr ));
17491787 }
17501788
17511789 if (delta.type == extent_types_t ::ROOT) {
@@ -1759,7 +1797,8 @@ Cache::replay_delta(
17591797 journal_seq, record_base, delta, *root);
17601798 root->set_modify_time (modify_time);
17611799 add_extent (root);
1762- return replay_delta_ertr::make_ready_future<bool >(true );
1800+ return replay_delta_ertr::make_ready_future<std::pair<bool , CachedExtentRef>>(
1801+ std::make_pair (true , root));
17631802 } else {
17641803 auto _get_extent_if_cached = [this ](paddr_t addr)
17651804 -> get_extent_ertr::future<CachedExtentRef> {
@@ -1799,17 +1838,26 @@ Cache::replay_delta(
17991838 DEBUG (" replay extent is not present, so delta is obsolete at {} {} -- {}" ,
18001839 journal_seq, record_base, delta);
18011840 assert (delta.pversion > 0 );
1802- return replay_delta_ertr::make_ready_future<bool >(true );
1841+ return replay_delta_ertr::make_ready_future<std::pair<bool , CachedExtentRef>>(
1842+ std::make_pair (false , nullptr ));
18031843 }
18041844
18051845 DEBUG (" replay extent delta at {} {} ... -- {}, prv_extent={}" ,
18061846 journal_seq, record_base, delta, *extent);
18071847
1808- assert (extent->last_committed_crc == delta.prev_crc );
1809- assert (extent->version == delta.pversion );
1810- extent->apply_delta_and_adjust_crc (record_base, delta.bl );
1811- extent->set_modify_time (modify_time);
1812- assert (extent->last_committed_crc == delta.final_crc );
1848+ if (delta.paddr .get_addr_type () == paddr_types_t ::SEGMENT ||
1849+ !can_inplace_rewrite (delta.type )) {
1850+ ceph_assert_always (extent->last_committed_crc == delta.prev_crc );
1851+ assert (extent->version == delta.pversion );
1852+ extent->apply_delta_and_adjust_crc (record_base, delta.bl );
1853+ extent->set_modify_time (modify_time);
1854+ ceph_assert_always (extent->last_committed_crc == delta.final_crc );
1855+ } else {
1856+ assert (delta.paddr .get_addr_type () == paddr_types_t ::RANDOM_BLOCK);
1857+ extent->apply_delta_and_adjust_crc (record_base, delta.bl );
1858+ extent->set_modify_time (modify_time);
1859+ // crc will be checked after journal replay is done
1860+ }
18131861
18141862 extent->version ++;
18151863 if (extent->version == 1 ) {
@@ -1821,7 +1869,8 @@ Cache::replay_delta(
18211869 journal_seq, record_base, delta, *extent);
18221870 }
18231871 mark_dirty (extent);
1824- return replay_delta_ertr::make_ready_future<bool >(true );
1872+ return replay_delta_ertr::make_ready_future<std::pair<bool , CachedExtentRef>>(
1873+ std::make_pair (true , extent));
18251874 });
18261875 }
18271876}
0 commit comments