@@ -739,7 +739,7 @@ void Cache::add_extent(CachedExtentRef ref)
739739void Cache::mark_dirty (CachedExtentRef ref)
740740{
741741 assert (ref->get_paddr ().is_absolute ());
742- if (ref->has_delta ()) {
742+ if (ref->is_stable_dirty ()) {
743743 assert (ref->primary_ref_list_hook .is_linked ());
744744 return ;
745745 }
@@ -753,15 +753,13 @@ void Cache::add_to_dirty(
753753 CachedExtentRef ref,
754754 const Transaction::src_t * p_src)
755755{
756- assert (ref->has_delta ());
756+ assert (ref->is_stable_dirty ());
757757 assert (!ref->primary_ref_list_hook .is_linked ());
758758 ceph_assert (ref->get_modify_time () != NULL_TIME);
759759 assert (ref->is_fully_loaded ());
760760 assert (ref->get_paddr ().is_absolute () ||
761761 ref->get_paddr ().is_root ());
762762
763- // Note: next might not be at extent_state_t::DIRTY,
764- // also see CachedExtent::is_stable_writting()
765763 intrusive_ptr_add_ref (&*ref);
766764 dirty.push_back (*ref);
767765
@@ -785,7 +783,7 @@ void Cache::remove_from_dirty(
785783 CachedExtentRef ref,
786784 const Transaction::src_t * p_src)
787785{
788- assert (ref->has_delta ());
786+ assert (ref->is_stable_dirty ());
789787 ceph_assert (ref->primary_ref_list_hook .is_linked ());
790788 assert (ref->is_fully_loaded ());
791789 assert (ref->get_paddr ().is_absolute () ||
@@ -817,13 +815,11 @@ void Cache::replace_dirty(
817815 CachedExtentRef prev,
818816 const Transaction::src_t & src)
819817{
820- assert (prev->has_delta ());
818+ assert (prev->is_stable_dirty ());
821819 ceph_assert (prev->primary_ref_list_hook .is_linked ());
822820 assert (prev->is_fully_loaded ());
823821
824- // Note: next might not be at extent_state_t::DIRTY,
825- // also see CachedExtent::is_stable_writting()
826- assert (next->has_delta ());
822+ assert (next->is_stable_dirty ());
827823 assert (!next->primary_ref_list_hook .is_linked ());
828824 ceph_assert (next->get_modify_time () != NULL_TIME);
829825 assert (next->is_fully_loaded ());
@@ -849,7 +845,7 @@ void Cache::clear_dirty()
849845{
850846 for (auto i = dirty.begin (); i != dirty.end (); ) {
851847 auto ptr = &*i;
852- assert (ptr->has_delta ());
848+ assert (ptr->is_stable_dirty ());
853849 ceph_assert (ptr->primary_ref_list_hook .is_linked ());
854850 assert (ptr->is_fully_loaded ());
855851
@@ -873,7 +869,7 @@ void Cache::remove_extent(
873869 assert (ref->is_valid ());
874870 assert (ref->get_paddr ().is_absolute () ||
875871 ref->get_paddr ().is_root ());
876- if (ref->has_delta ()) {
872+ if (ref->is_stable_dirty ()) {
877873 remove_from_dirty (ref, p_src);
878874 } else if (!ref->is_placeholder ()) {
879875 assert (ref->get_paddr ().is_absolute ());
@@ -905,21 +901,18 @@ void Cache::commit_replace_extent(
905901
906902 const auto t_src = t.get_src ();
907903 if (is_root_type (prev->get_type ())) {
908- assert (prev->is_stable_clean ()
909- || prev->primary_ref_list_hook .is_linked ());
910- if (prev->has_delta ()) {
911- // add the new dirty root to front
912- remove_from_dirty (prev, nullptr /* exclude root */ );
913- }
904+ assert (prev->is_stable_dirty ());
905+ assert (prev->primary_ref_list_hook .is_linked ());
906+ // add the new dirty root to front
907+ remove_from_dirty (prev, nullptr /* exclude root */ );
914908 add_to_dirty (next, nullptr /* exclude root */ );
915- } else if (prev->has_delta ()) {
909+ } else if (prev->is_stable_dirty ()) {
916910 replace_dirty (next, prev, t_src);
917911 } else {
918912 lru.remove_from_lru (*prev);
919913 add_to_dirty (next, &t_src);
920914 }
921915
922- next->on_replace_prior ();
923916 invalidate_extent (t, *prev);
924917}
925918
@@ -1306,14 +1299,9 @@ record_t Cache::prepare_record(
13061299 i->prepare_commit ();
13071300
13081301 if (i->is_mutation_pending ()) {
1309- i->set_io_wait ();
1310- // extent with EXIST_MUTATION_PENDING doesn't have
1311- // prior_instance field so skip these extents.
1312- // the existing extents should be added into Cache
1313- // during complete_commit to sync with gc transaction.
1314- commit_replace_extent (t, i, i->prior_instance );
1315- } // Note, else, add_extent() below
1316- // Note, i->state become DIRTY in complete_commit()
1302+ i->on_replace_prior ();
1303+ } // else, is_exist_mutation_pending():
1304+ // - it doesn't have prior_instance to replace
13171305
13181306 assert (i->get_version () > 0 );
13191307 auto final_crc = i->calc_crc32c ();
@@ -1381,6 +1369,24 @@ record_t Cache::prepare_record(
13811369 e->prepare_commit ();
13821370 });
13831371
1372+ /*
1373+ * We can only update extent states after the logical linked tree is
1374+ * resolved:
1375+ * - on_replace_prior()
1376+ * - prepare_commit()
1377+ */
1378+ for (auto &i: t.mutated_block_list ) {
1379+ if (i->is_valid ()) {
1380+ if (i->is_mutation_pending ()) {
1381+ i->set_io_wait (CachedExtent::extent_state_t ::DIRTY);
1382+ commit_replace_extent (t, i, i->prior_instance );
1383+ } // else, is_exist_mutation_pending():
1384+ // - it doesn't have prior_instance to replace
1385+ // - and add_extent() atomically below
1386+ // - set_io_wait(DIRTY) atomically below
1387+ }
1388+ }
1389+
13841390 // Transaction is now a go, set up in-memory cache state
13851391 // invalidate now invalid blocks
13861392 io_stat_t retire_stat;
@@ -1493,7 +1499,7 @@ record_t Cache::prepare_record(
14931499 i->get_length (),
14941500 i->get_type ()));
14951501 }
1496- i->set_io_wait ();
1502+ i->set_io_wait (CachedExtent:: extent_state_t ::CLEAN );
14971503 // Note, paddr is known until complete_commit(),
14981504 // so add_extent() later.
14991505 }
@@ -1519,7 +1525,7 @@ record_t Cache::prepare_record(
15191525 i->get_length (),
15201526 i->get_type ()));
15211527 }
1522- i->set_io_wait ();
1528+ i->set_io_wait (CachedExtent:: extent_state_t ::CLEAN );
15231529 // Note, paddr is (can be) known until complete_commit(),
15241530 // so add_extent() later.
15251531 }
@@ -1530,12 +1536,15 @@ record_t Cache::prepare_record(
15301536 }
15311537 assert (i->state == CachedExtent::extent_state_t ::DIRTY);
15321538 assert (i->version > 0 );
1539+ assert (i->pending_for_transaction == TRANS_ID_NULL);
1540+ assert (!i->prior_instance );
15331541 remove_from_dirty (i, &trans_src);
15341542 // set the version to zero because the extent state is now clean
15351543 // in order to handle this transparently
15361544 i->version = 0 ;
15371545 i->dirty_from = JOURNAL_SEQ_MIN;
1538- // no set_io_wait()
1546+ // no set_io_wait(), skip complete_commit()
1547+ assert (!i->is_pending_io ());
15391548 i->state = CachedExtent::extent_state_t ::CLEAN;
15401549 assert (i->is_logical ());
15411550 i->clear_modified_region ();
@@ -1557,18 +1566,21 @@ record_t Cache::prepare_record(
15571566 }
15581567
15591568 if (i->is_exist_clean ()) {
1560- // no set_io_wait()
1569+ assert (i->version == 0 );
1570+ assert (!i->prior_instance );
1571+ // no set_io_wait(), skip complete_commit()
1572+ assert (!i->is_pending_io ());
1573+ i->pending_for_transaction = TRANS_ID_NULL;
15611574 i->state = CachedExtent::extent_state_t ::CLEAN;
15621575 } else {
15631576 assert (i->is_exist_mutation_pending ());
1564- i->set_io_wait ();
1565- // Note, i->state become DIRTY in complete_commit()
1577+ i->set_io_wait (CachedExtent::extent_state_t ::DIRTY);
15661578 }
15671579
15681580 // exist mutation pending extents must be in t.mutated_block_list
15691581 add_extent (i);
15701582 const auto t_src = t.get_src ();
1571- if (i->has_delta ()) {
1583+ if (i->is_stable_dirty ()) {
15721584 add_to_dirty (i, &t_src);
15731585 } else {
15741586 touch_extent (*i, &t_src, t.get_cache_hint ());
@@ -1794,6 +1806,7 @@ void Cache::complete_commit(
17941806 return ;
17951807 }
17961808
1809+ assert (i->is_stable_clean_pending ());
17971810 bool is_inline = false ;
17981811 if (i->is_inline ()) {
17991812 is_inline = true ;
@@ -1808,14 +1821,11 @@ void Cache::complete_commit(
18081821#endif
18091822 i->pending_for_transaction = TRANS_ID_NULL;
18101823 i->on_initial_write ();
1811-
1812- i->state = CachedExtent::extent_state_t ::CLEAN;
18131824 i->reset_prior_instance ();
18141825 DEBUGT (" add extent as fresh, inline={} -- {}" ,
18151826 t, is_inline, *i);
18161827 i->invalidate_hints ();
18171828 add_extent (i);
1818- assert (!i->has_delta ());
18191829 const auto t_src = t.get_src ();
18201830 touch_extent (*i, &t_src, t.get_cache_hint ());
18211831 i->complete_io ();
@@ -1858,12 +1868,14 @@ void Cache::complete_commit(
18581868 if (!i->is_valid ()) {
18591869 continue ;
18601870 }
1861- assert (i->is_exist_mutation_pending () ||
1862- i->prior_instance );
1871+ assert (i->is_stable_dirty ());
1872+ assert (i->is_pending_io ());
1873+ assert (i->io_wait ->from_state == CachedExtent::extent_state_t ::EXIST_MUTATION_PENDING
1874+ || (i->io_wait ->from_state == CachedExtent::extent_state_t ::MUTATION_PENDING
1875+ && i->prior_instance ));
18631876 i->on_delta_write (final_block_start);
18641877 i->pending_for_transaction = TRANS_ID_NULL;
18651878 i->reset_prior_instance ();
1866- i->state = CachedExtent::extent_state_t ::DIRTY;
18671879 assert (i->version > 0 );
18681880 if (i->version == 1 || is_root_type (i->get_type ())) {
18691881 i->dirty_from = start_seq;
0 commit comments