@@ -1315,6 +1315,10 @@ bool disk_log_impl::is_cloud_retention_active() const {
13151315 && (config ().is_archival_enabled ());
13161316}
13171317
1318+ bool disk_log_impl::is_cloud_gc_active () const {
1319+ return is_cloud_retention_active () || config ().is_tiered_cloud ();
1320+ }
1321+
13181322/*
13191323 * applies overrides for non-cloud storage settings
13201324 */
@@ -1779,7 +1783,11 @@ ss::future<std::optional<model::offset>> disk_log_impl::do_gc(gc_config cfg) {
17791783 * process such as disk space management drives this process such that after
17801784 * a round of gc has run the intent flag can be cleared.
17811785 */
1782- if (_cloud_gc_offset.has_value ()) {
1786+ // Cloud-topic (tiered_cloud) partitions do not evict through do_gc /
1787+ // request_eviction_until_offset; ctp_stm consumes _cloud_gc_offset via
1788+ // compute_gc_offset instead. Leave the pin alone for them so do_gc does not
1789+ // steal and discard it before ctp_stm sees it.
1790+ if (_cloud_gc_offset.has_value () && !config ().is_tiered_cloud ()) {
17831791 const auto offset = _cloud_gc_offset.value ();
17841792 _cloud_gc_offset.reset ();
17851793
@@ -1912,20 +1920,29 @@ disk_log_impl::maybe_adjusted_retention_offset(gc_config cfg) {
19121920
19131921ss::future<std::optional<model::offset>>
19141922disk_log_impl::compute_gc_offset (gc_config cfg) {
1915- // Single GC-offset computation shared by gc() housekeeping and by
1916- // ctp_stm for cloud-topic partitions. The offset is retention-driven
1917- // unless space management has pinned _cloud_gc_offset, which then takes
1918- // precedence. maybe_apply_local_storage_overrides
1919- // bypasses the is_cloud_retention_active() gate for cloud-topic partitions
1920- // (the gate is false for storage.mode in {cloud, tiered_cloud}), so the
1921- // local-target override engages there under retention_local_strict.
1923+ // Single GC-offset computation shared by gc() housekeeping and by ctp_stm
1924+ // for cloud-topic partitions. Retention (time/bytes plus the local-storage
1925+ // overrides, which maybe_apply_local_storage_overrides engages for
1926+ // cloud-topic partitions under retention_local_strict even though the
1927+ // is_cloud_retention_active() gate is false) sets the base offset. Space
1928+ // management can raise it under disk pressure via a pinned
1929+ // _cloud_gc_offset.
1930+ //
1931+ // ctp_stm is the sole consumer of the pin for cloud topics (do_gc leaves it
1932+ // alone), so consume it here instead of letting it persist: a stale pin
1933+ // would otherwise keep shadowing retention after disk pressure relents.
1934+ // Fold it with retention so the pin only ever raises the trim point.
19221935 cfg = apply_kafka_retention_overrides (cfg);
1923- if (_cloud_gc_offset.has_value ()) {
1924- co_return _cloud_gc_offset;
1925- }
19261936 co_await maybe_adjust_retention_timestamps ();
19271937 cfg = maybe_apply_local_storage_overrides (cfg);
1928- co_return retention_offset (cfg);
1938+ auto retention = retention_offset (cfg);
1939+
1940+ auto pin = _cloud_gc_offset;
1941+ _cloud_gc_offset.reset ();
1942+ if (pin.has_value ()) {
1943+ co_return retention.has_value () ? std::max (*retention, *pin) : pin;
1944+ }
1945+ co_return retention;
19291946}
19301947
19311948std::optional<model::offset>
@@ -3921,7 +3938,7 @@ disk_log_impl::disk_usage_and_reclaimable_space(gc_config input_cfg) {
39213938 && seg->offsets ().get_dirty_offset () <= retention_offset.value ()) {
39223939 retention_segments.push_back (seg);
39233940 } else if (
3924- is_cloud_retention_active ()
3941+ is_cloud_gc_active ()
39253942 && seg->offsets ().get_dirty_offset () <= max_removable) {
39263943 available_segments.push_back (seg);
39273944 } else {
@@ -3937,8 +3954,8 @@ disk_log_impl::disk_usage_and_reclaimable_space(gc_config input_cfg) {
39373954 * get_reclaimable_offsets is going to be merged together.
39383955 */
39393956 if (
3940- !config ().is_read_replica_mode_enabled ()
3941- && is_cloud_retention_active () && seg != _segs.back ()
3957+ !config ().is_read_replica_mode_enabled () && is_cloud_gc_active ()
3958+ && seg != _segs.back ()
39423959 && seg->offsets ().get_dirty_offset () <= max_removable
39433960 && local_retention_offset.has_value ()
39443961 && seg->offsets ().get_dirty_offset ()
@@ -4279,8 +4296,8 @@ ss::future<usage_report> disk_log_impl::disk_usage(gc_config cfg) {
42794296chunked_vector<ss::lw_shared_ptr<segment>>
42804297disk_log_impl::cloud_gc_eligible_segments () {
42814298 vassert (
4282- is_cloud_retention_active (),
4283- " Expected {} to have cloud retention enabled " ,
4299+ is_cloud_gc_active (),
4300+ " Expected cloud GC to be active for {} " ,
42844301 config ().ntp ());
42854302
42864303 constexpr size_t keep_segs = 1 ;
@@ -4313,7 +4330,7 @@ disk_log_impl::cloud_gc_eligible_segments() {
43134330}
43144331
43154332void disk_log_impl::set_cloud_gc_offset (model::offset offset) {
4316- if (!is_cloud_retention_active ()) {
4333+ if (!is_cloud_gc_active ()) {
43174334 vlog (
43184335 stlog.debug ,
43194336 " Ignoring request to set GC offset on non-cloud enabled partition "
@@ -4338,7 +4355,7 @@ disk_log_impl::get_reclaimable_offsets(gc_config cfg) {
43384355
43394356 reclaimable_offsets res;
43404357
4341- if (!is_cloud_retention_active ()) {
4358+ if (!is_cloud_gc_active ()) {
43424359 vlog (
43434360 stlog.debug ,
43444361 " Reporting no reclaimable offsets for non-cloud partition {}" ,
@@ -4540,7 +4557,7 @@ size_t disk_log_impl::reclaimable_size_bytes() const {
45404557 * local retention size may change. catch these before reporting potentially
45414558 * stale information.
45424559 */
4543- if (!is_cloud_retention_active ()) {
4560+ if (!is_cloud_gc_active ()) {
45444561 return 0 ;
45454562 }
45464563 if (config ().is_read_replica_mode_enabled ()) {
0 commit comments