@@ -750,6 +750,9 @@ void Cache::add_to_dirty(CachedExtentRef ref)
750750 assert (ref->is_dirty ());
751751 assert (!ref->primary_ref_list_hook .is_linked ());
752752 ceph_assert (ref->get_modify_time () != NULL_TIME);
753+
754+ // Note: next might not be at extent_state_t::DIRTY,
755+ // also see CachedExtent::is_stable_writting()
753756 intrusive_ptr_add_ref (&*ref);
754757 dirty.push_back (*ref);
755758 stats.dirty_bytes += ref->get_length ();
@@ -759,11 +762,51 @@ void Cache::remove_from_dirty(CachedExtentRef ref)
759762{
760763 assert (ref->is_dirty ());
761764 ceph_assert (ref->primary_ref_list_hook .is_linked ());
765+
762766 stats.dirty_bytes -= ref->get_length ();
763767 dirty.erase (dirty.s_iterator_to (*ref));
764768 intrusive_ptr_release (&*ref);
765769}
766770
771+ void Cache::replace_dirty (
772+ CachedExtentRef next,
773+ CachedExtentRef prev)
774+ {
775+ assert (prev->is_dirty ());
776+ ceph_assert (prev->primary_ref_list_hook .is_linked ());
777+
778+ // Note: next might not be at extent_state_t::DIRTY,
779+ // also see CachedExtent::is_stable_writting()
780+ assert (next->is_dirty ());
781+ assert (!next->primary_ref_list_hook .is_linked ());
782+ ceph_assert (next->get_modify_time () != NULL_TIME);
783+
784+ assert (prev->get_dirty_from () == next->get_dirty_from ());
785+ assert (prev->get_length () == next->get_length ());
786+ assert (!is_root_type (next->get_type ()));
787+ assert (prev->get_type () == next->get_type ());
788+
789+ auto prev_it = dirty.iterator_to (*prev);
790+ dirty.insert (prev_it, *next);
791+ dirty.erase (prev_it);
792+ intrusive_ptr_release (&*prev);
793+ intrusive_ptr_add_ref (&*next);
794+ }
795+
796+ void Cache::clear_dirty ()
797+ {
798+ for (auto i = dirty.begin (); i != dirty.end (); ) {
799+ auto ptr = &*i;
800+ assert (ptr->is_dirty ());
801+ ceph_assert (ptr->primary_ref_list_hook .is_linked ());
802+
803+ stats.dirty_bytes -= ptr->get_length ();
804+ dirty.erase (i++);
805+ intrusive_ptr_release (ptr);
806+ }
807+ assert (stats.dirty_bytes == 0 );
808+ }
809+
767810void Cache::remove_extent (CachedExtentRef ref)
768811{
769812 assert (ref->is_valid ());
@@ -790,7 +833,6 @@ void Cache::commit_replace_extent(
790833 CachedExtentRef next,
791834 CachedExtentRef prev)
792835{
793- assert (next->is_dirty ());
794836 assert (next->get_paddr () == prev->get_paddr ());
795837 assert (next->version == prev->version + 1 );
796838 extents.replace (*next, *prev);
@@ -799,19 +841,12 @@ void Cache::commit_replace_extent(
799841 assert (prev->is_stable_clean ()
800842 || prev->primary_ref_list_hook .is_linked ());
801843 if (prev->is_dirty ()) {
802- stats.dirty_bytes -= prev->get_length ();
803- dirty.erase (dirty.s_iterator_to (*prev));
804- intrusive_ptr_release (&*prev);
844+ // add the new dirty root to front
845+ remove_from_dirty (prev);
805846 }
806847 add_to_dirty (next);
807848 } else if (prev->is_dirty ()) {
808- assert (prev->get_dirty_from () == next->get_dirty_from ());
809- assert (prev->primary_ref_list_hook .is_linked ());
810- auto prev_it = dirty.iterator_to (*prev);
811- dirty.insert (prev_it, *next);
812- dirty.erase (prev_it);
813- intrusive_ptr_release (&*prev);
814- intrusive_ptr_add_ref (&*next);
849+ replace_dirty (next, prev);
815850 } else {
816851 lru.remove_from_lru (*prev);
817852 add_to_dirty (next);
@@ -1752,15 +1787,9 @@ Cache::close_ertr::future<> Cache::close()
17521787 extents.size (),
17531788 extents.get_bytes ());
17541789 root.reset ();
1755- for (auto i = dirty.begin (); i != dirty.end (); ) {
1756- auto ptr = &*i;
1757- stats.dirty_bytes -= ptr->get_length ();
1758- dirty.erase (i++);
1759- intrusive_ptr_release (ptr);
1760- }
1790+ clear_dirty ();
17611791 backref_extents.clear ();
17621792 backref_entryrefs_by_seq.clear ();
1763- assert (stats.dirty_bytes == 0 );
17641793 lru.clear ();
17651794 return close_ertr::now ();
17661795}
0 commit comments