@@ -125,6 +125,7 @@ struct xfs_zone_gc_iter {
125125 */
126126struct xfs_zone_gc_data {
127127 struct xfs_mount * mp ;
128+ struct xfs_open_zone * oz ;
128129
129130 /* bioset used to allocate the gc_bios */
130131 struct bio_set bio_set ;
@@ -525,9 +526,10 @@ xfs_zone_gc_select_victim(
525526}
526527
527528static int
528- xfs_zone_gc_steal_open (
529- struct xfs_zone_info * zi )
529+ xfs_zone_gc_steal_open_zone (
530+ struct xfs_zone_gc_data * data )
530531{
532+ struct xfs_zone_info * zi = data -> mp -> m_zone_info ;
531533 struct xfs_open_zone * oz , * found = NULL ;
532534
533535 spin_lock (& zi -> zi_open_zones_lock );
@@ -542,10 +544,12 @@ xfs_zone_gc_steal_open(
542544
543545 trace_xfs_zone_gc_target_stolen (found -> oz_rtg );
544546 found -> oz_is_gc = true;
545- list_del_init (& found -> oz_entry );
546547 zi -> zi_nr_open_zones -- ;
547- zi -> zi_open_gc_zone = found ;
548+ zi -> zi_nr_open_gc_zones ++ ;
548549 spin_unlock (& zi -> zi_open_zones_lock );
550+
551+ atomic_inc (& found -> oz_ref );
552+ data -> oz = found ;
549553 return 0 ;
550554}
551555
@@ -554,39 +558,43 @@ xfs_zone_gc_steal_open(
554558 */
555559static bool
556560xfs_zone_gc_select_target (
557- struct xfs_mount * mp )
561+ struct xfs_zone_gc_data * data )
558562{
559- struct xfs_zone_info * zi = mp -> m_zone_info ;
560- struct xfs_open_zone * oz = zi -> zi_open_gc_zone ;
563+ struct xfs_zone_info * zi = data -> mp -> m_zone_info ;
561564
562- if (oz ) {
565+ if (data -> oz ) {
563566 /*
564567 * If we have space available, just keep using the existing
565568 * zone.
566569 */
567- if (oz -> oz_allocated < rtg_blocks (oz -> oz_rtg ))
570+ if (data -> oz -> oz_allocated < rtg_blocks (data -> oz -> oz_rtg ))
568571 return true;
569572
570573 /*
571574 * Wait for all writes to the current zone to finish before
572575 * picking a new one.
573576 */
574- if (oz -> oz_written < rtg_blocks (oz -> oz_rtg ))
577+ if (data -> oz -> oz_written < rtg_blocks (data -> oz -> oz_rtg ))
575578 return false;
579+
580+ xfs_open_zone_put (data -> oz );
576581 }
577582
578583 /*
579584 * Open a new zone when there is none currently in use.
580585 */
581586 ASSERT (zi -> zi_nr_open_zones <=
582- mp -> m_max_open_zones - XFS_OPEN_GC_ZONES );
583- oz = xfs_open_zone (mp , WRITE_LIFE_NOT_SET , true);
584- if (oz )
585- trace_xfs_zone_gc_target_opened (oz -> oz_rtg );
587+ data -> mp -> m_max_open_zones - XFS_OPEN_GC_ZONES );
588+ data -> oz = xfs_open_zone (data -> mp , WRITE_LIFE_NOT_SET , true);
589+ if (!data -> oz )
590+ return false;
591+ trace_xfs_zone_gc_target_opened (data -> oz -> oz_rtg );
592+ atomic_inc (& data -> oz -> oz_ref );
586593 spin_lock (& zi -> zi_open_zones_lock );
587- zi -> zi_open_gc_zone = oz ;
594+ zi -> zi_nr_open_gc_zones ++ ;
595+ list_add_tail (& data -> oz -> oz_entry , & zi -> zi_open_zones );
588596 spin_unlock (& zi -> zi_open_zones_lock );
589- return !! oz ;
597+ return true ;
590598}
591599
592600static void
@@ -609,7 +617,7 @@ xfs_zone_gc_alloc_blocks(
609617 bool * is_seq )
610618{
611619 struct xfs_mount * mp = data -> mp ;
612- struct xfs_open_zone * oz = mp -> m_zone_info -> zi_open_gc_zone ;
620+ struct xfs_open_zone * oz = data -> oz ;
613621
614622 * count_fsb = min (* count_fsb , XFS_B_TO_FSB (mp , data -> scratch_available ));
615623
@@ -683,7 +691,7 @@ xfs_zone_gc_can_start_chunk(
683691 return false;
684692 }
685693
686- return xfs_zone_gc_select_target (data -> mp );
694+ return xfs_zone_gc_select_target (data );
687695}
688696
689697static bool
@@ -728,7 +736,7 @@ xfs_zone_gc_start_chunk(
728736 chunk -> new_daddr = daddr ;
729737 chunk -> is_seq = is_seq ;
730738 chunk -> data = data ;
731- chunk -> oz = mp -> m_zone_info -> zi_open_gc_zone ;
739+ chunk -> oz = data -> oz ;
732740 chunk -> victim_rtg = iter -> victim_rtg ;
733741 atomic_inc (& rtg_group (chunk -> victim_rtg )-> xg_active_ref );
734742 atomic_inc (& chunk -> victim_rtg -> rtg_gccount );
@@ -1134,6 +1142,8 @@ xfs_zoned_gcd(
11341142 }
11351143 xfs_clear_zonegc_running (mp );
11361144
1145+ if (data -> oz )
1146+ xfs_open_zone_put (data -> oz );
11371147 if (data -> iter .victim_rtg )
11381148 xfs_rtgroup_rele (data -> iter .victim_rtg );
11391149
@@ -1183,6 +1193,10 @@ xfs_zone_gc_mount(
11831193 struct xfs_zone_gc_data * data ;
11841194 int error ;
11851195
1196+ data = xfs_zone_gc_data_alloc (mp );
1197+ if (!data )
1198+ return - ENOMEM ;
1199+
11861200 /*
11871201 * If there are no free zones available for GC, or the number of open
11881202 * zones has reached the open zone limit, pick the open zone with
@@ -1192,35 +1206,30 @@ xfs_zone_gc_mount(
11921206 */
11931207 if (!xfs_group_marked (mp , XG_TYPE_RTG , XFS_RTG_FREE ) ||
11941208 zi -> zi_nr_open_zones >= mp -> m_max_open_zones ) {
1195- error = xfs_zone_gc_steal_open ( zi );
1209+ error = xfs_zone_gc_steal_open_zone ( data );
11961210 if (error ) {
11971211 xfs_warn (mp , "unable to steal an open zone for gc" );
1198- return error ;
1212+ goto out_free_gc_data ;
11991213 }
12001214 }
12011215
1202- data = xfs_zone_gc_data_alloc (mp );
1203- if (!data ) {
1204- error = - ENOMEM ;
1205- goto out_put_gc_zone ;
1206- }
1207-
12081216 zi -> zi_gc_thread = kthread_create (xfs_zoned_gcd , data ,
12091217 "xfs-zone-gc/%s" , mp -> m_super -> s_id );
12101218 if (IS_ERR (zi -> zi_gc_thread )) {
12111219 xfs_warn (mp , "unable to create zone gc thread" );
12121220 error = PTR_ERR (zi -> zi_gc_thread );
1213- goto out_free_gc_data ;
1221+ goto out_put_oz ;
12141222 }
12151223
12161224 /* xfs_zone_gc_start will unpark for rw mounts */
12171225 kthread_park (zi -> zi_gc_thread );
12181226 return 0 ;
12191227
1228+ out_put_oz :
1229+ if (data -> oz )
1230+ xfs_open_zone_put (data -> oz );
12201231out_free_gc_data :
12211232 kfree (data );
1222- out_put_gc_zone :
1223- xfs_open_zone_put (zi -> zi_open_gc_zone );
12241233 return error ;
12251234}
12261235
@@ -1231,6 +1240,4 @@ xfs_zone_gc_unmount(
12311240 struct xfs_zone_info * zi = mp -> m_zone_info ;
12321241
12331242 kthread_stop (zi -> zi_gc_thread );
1234- if (zi -> zi_open_gc_zone )
1235- xfs_open_zone_put (zi -> zi_open_gc_zone );
12361243}
0 commit comments