xref: /aosp_15_r20/system/extras/checkpoint_gc/checkpoint_gc.sh (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker#!/system/bin/sh
2*288bf522SAndroid Build Coastguard Worker
3*288bf522SAndroid Build Coastguard Worker#
4*288bf522SAndroid Build Coastguard Worker# Copyright (C) 2019 The Android Open Source Project
5*288bf522SAndroid Build Coastguard Worker#
6*288bf522SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
7*288bf522SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
8*288bf522SAndroid Build Coastguard Worker# You may obtain a copy of the License at
9*288bf522SAndroid Build Coastguard Worker#
10*288bf522SAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
11*288bf522SAndroid Build Coastguard Worker#
12*288bf522SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
13*288bf522SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
14*288bf522SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*288bf522SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
16*288bf522SAndroid Build Coastguard Worker# limitations under the License.
17*288bf522SAndroid Build Coastguard Worker#
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker# This script will run as an pre-checkpointing cleanup for mounting f2fs
20*288bf522SAndroid Build Coastguard Worker# with checkpoint=disable, so that the first mount after the reboot will
21*288bf522SAndroid Build Coastguard Worker# be faster. It is unnecessary to run if the device does not use userdata
22*288bf522SAndroid Build Coastguard Worker# checkpointing on F2FS.
23*288bf522SAndroid Build Coastguard Worker
24*288bf522SAndroid Build Coastguard Worker# TARGET_SLOT="${1}"
25*288bf522SAndroid Build Coastguard WorkerSTATUS_FD="${2}"
26*288bf522SAndroid Build Coastguard Worker
27*288bf522SAndroid Build Coastguard WorkerSLEEP=5
28*288bf522SAndroid Build Coastguard WorkerTIME=0
29*288bf522SAndroid Build Coastguard WorkerMAX_TIME=1200
30*288bf522SAndroid Build Coastguard Worker
31*288bf522SAndroid Build Coastguard Worker# GC_URGENT_MID, will fall back to GC_URGENT_HIGH if unsupported
32*288bf522SAndroid Build Coastguard WorkerGC_TYPE=3
33*288bf522SAndroid Build Coastguard Worker
34*288bf522SAndroid Build Coastguard Worker# If we fall back, start off with less impactful GC
35*288bf522SAndroid Build Coastguard Worker# To avoid long wait time, ramp up over time
36*288bf522SAndroid Build Coastguard WorkerGC_SLEEP_MAX=150
37*288bf522SAndroid Build Coastguard WorkerGC_SLEEP_MIN=50
38*288bf522SAndroid Build Coastguard WorkerGC_SLEEP_STEP=5
39*288bf522SAndroid Build Coastguard Worker
40*288bf522SAndroid Build Coastguard Worker# We only need to run this if we're using f2fs
41*288bf522SAndroid Build Coastguard Workerif [ ! -f /dev/sys/fs/by-name/userdata/gc_urgent ]; then
42*288bf522SAndroid Build Coastguard Worker  exit 0
43*288bf522SAndroid Build Coastguard Workerfi
44*288bf522SAndroid Build Coastguard Worker
45*288bf522SAndroid Build Coastguard Worker# If we have sufficient free segments, it doesn't matter how much extra
46*288bf522SAndroid Build Coastguard Worker# space is unusable, since we only need to make it to boot complete to
47*288bf522SAndroid Build Coastguard Worker# get that space back
48*288bf522SAndroid Build Coastguard WorkerMIN_FREE_SEGMENT=500
49*288bf522SAndroid Build Coastguard Worker
50*288bf522SAndroid Build Coastguard Worker# Ideally we want to track unusable, as it directly measures what we
51*288bf522SAndroid Build Coastguard Worker# care about. If it's not present, dirty_segments is the best proxy.
52*288bf522SAndroid Build Coastguard Workerif [ -f /dev/sys/fs/by-name/userdata/unusable ]; then
53*288bf522SAndroid Build Coastguard Worker  UNUSABLE=1
54*288bf522SAndroid Build Coastguard Worker  METRIC="unusable blocks"
55*288bf522SAndroid Build Coastguard Worker  THRESHOLD=25000
56*288bf522SAndroid Build Coastguard Worker  MAX_INCREASE=500
57*288bf522SAndroid Build Coastguard Worker  read START < /dev/sys/fs/by-name/userdata/unusable
58*288bf522SAndroid Build Coastguard Workerelse
59*288bf522SAndroid Build Coastguard Worker  METRIC="dirty segments"
60*288bf522SAndroid Build Coastguard Worker  THRESHOLD=200
61*288bf522SAndroid Build Coastguard Worker  MAX_INCREASE=5
62*288bf522SAndroid Build Coastguard Worker  read START < /dev/sys/fs/by-name/userdata/dirty_segments
63*288bf522SAndroid Build Coastguard Workerfi
64*288bf522SAndroid Build Coastguard Worker
65*288bf522SAndroid Build Coastguard Workerlog -pi -t checkpoint_gc Turning on GC for userdata
66*288bf522SAndroid Build Coastguard Worker
67*288bf522SAndroid Build Coastguard Workerread OLD_SLEEP < /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time || \
68*288bf522SAndroid Build Coastguard Worker  { log -pw -t checkpoint_gc Cannot read gc_urgent_sleep_time; exit 1; }
69*288bf522SAndroid Build Coastguard WorkerGC_SLEEP=${GC_SLEEP_MAX}
70*288bf522SAndroid Build Coastguard Workerecho ${GC_SLEEP} > /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time || \
71*288bf522SAndroid Build Coastguard Worker  { log -pw -t checkpoint_gc Cannot set gc_urgent_sleep_time; exit 1; }
72*288bf522SAndroid Build Coastguard Worker
73*288bf522SAndroid Build Coastguard Worker
74*288bf522SAndroid Build Coastguard Workerecho ${GC_TYPE} > /dev/sys/fs/by-name/userdata/gc_urgent \
75*288bf522SAndroid Build Coastguard Worker  || { GC_TYPE=1; log -pi -t checkpoint_gc GC_URGENT_MID not supported, using GC_URGENT_HIGH; }
76*288bf522SAndroid Build Coastguard Worker
77*288bf522SAndroid Build Coastguard Workerif [ ${GC_TYPE} -eq 1 ]; then
78*288bf522SAndroid Build Coastguard Worker  echo ${GC_TYPE} > /dev/sys/fs/by-name/userdata/gc_urgent || \
79*288bf522SAndroid Build Coastguard Worker    { echo ${OLD_SLEEP} > /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time; \
80*288bf522SAndroid Build Coastguard Worker    log -pw -t checkpoint_gc Failed to set gc_urgent; exit 1; }
81*288bf522SAndroid Build Coastguard Workerelse
82*288bf522SAndroid Build Coastguard Worker  # GC MID will wait for background I/O, so no need to start small
83*288bf522SAndroid Build Coastguard Worker  GC_SLEEP=${GC_SLEEP_MIN}
84*288bf522SAndroid Build Coastguard Workerfi
85*288bf522SAndroid Build Coastguard Worker
86*288bf522SAndroid Build Coastguard Worker
87*288bf522SAndroid Build Coastguard WorkerCURRENT=${START}
88*288bf522SAndroid Build Coastguard WorkerTODO=$((${START}-${THRESHOLD}))
89*288bf522SAndroid Build Coastguard WorkerCUTOFF=$((${START} + ${MAX_INCREASE}))
90*288bf522SAndroid Build Coastguard Workerwhile [ ${CURRENT} -gt ${THRESHOLD} ]; do
91*288bf522SAndroid Build Coastguard Worker  log -pi -t checkpoint_gc ${METRIC}:${CURRENT} \(threshold:${THRESHOLD}\) mode:${GC_TYPE} GC_SLEEP:${GC_SLEEP}
92*288bf522SAndroid Build Coastguard Worker  PROGRESS=`echo "(${START}-${CURRENT})/${TODO}"|bc -l`
93*288bf522SAndroid Build Coastguard Worker  if [[ $PROGRESS == -* ]]; then
94*288bf522SAndroid Build Coastguard Worker      PROGRESS=0
95*288bf522SAndroid Build Coastguard Worker  fi
96*288bf522SAndroid Build Coastguard Worker  print -u${STATUS_FD} "global_progress ${PROGRESS}"
97*288bf522SAndroid Build Coastguard Worker  if [ ${UNUSABLE} -eq 1 ]; then
98*288bf522SAndroid Build Coastguard Worker    read CURRENT < /dev/sys/fs/by-name/userdata/unusable
99*288bf522SAndroid Build Coastguard Worker  else
100*288bf522SAndroid Build Coastguard Worker    read CURRENT < /dev/sys/fs/by-name/userdata/dirty_segments
101*288bf522SAndroid Build Coastguard Worker  fi
102*288bf522SAndroid Build Coastguard Worker
103*288bf522SAndroid Build Coastguard Worker  if [ ${CURRENT} -gt ${CUTOFF} ]; then
104*288bf522SAndroid Build Coastguard Worker    log -pw -t checkpoint_gc Garbage Collection is making no progress. Aborting checkpoint_gc attempt \(initial ${METRIC}: ${START}, now: ${CURRENT}\)
105*288bf522SAndroid Build Coastguard Worker    break
106*288bf522SAndroid Build Coastguard Worker  fi
107*288bf522SAndroid Build Coastguard Worker
108*288bf522SAndroid Build Coastguard Worker  read CURRENT_FREE_SEGMENTS < /dev/sys/fs/by-name/userdata/free_segments
109*288bf522SAndroid Build Coastguard Worker  read CURRENT_OVP < /dev/sys/fs/by-name/userdata/ovp_segments
110*288bf522SAndroid Build Coastguard Worker  CURRENT_FREE_SEG=$((${CURRENT_FREE_SEGMENTS}-${CURRENT_OVP}))
111*288bf522SAndroid Build Coastguard Worker  if [ ${CURRENT_FREE_SEG} -gt ${MIN_FREE_SEGMENT} ]; then
112*288bf522SAndroid Build Coastguard Worker    log -pi checkpoint_gc Sufficient free segments. Extra gc not needed.
113*288bf522SAndroid Build Coastguard Worker    break
114*288bf522SAndroid Build Coastguard Worker  fi
115*288bf522SAndroid Build Coastguard Worker
116*288bf522SAndroid Build Coastguard Worker  sleep ${SLEEP}
117*288bf522SAndroid Build Coastguard Worker  TIME=$((${TIME}+${SLEEP}))
118*288bf522SAndroid Build Coastguard Worker  if [ ${TIME} -gt ${MAX_TIME} ]; then
119*288bf522SAndroid Build Coastguard Worker    log -pw -t checkpoint_gc Timed out with gc threshold not met.
120*288bf522SAndroid Build Coastguard Worker    break
121*288bf522SAndroid Build Coastguard Worker  fi
122*288bf522SAndroid Build Coastguard Worker  if [ ${GC_SLEEP} -gt ${GC_SLEEP_MIN} ]; then
123*288bf522SAndroid Build Coastguard Worker    GC_SLEEP=$((${GC_SLEEP}-${GC_SLEEP_STEP}))
124*288bf522SAndroid Build Coastguard Worker  fi
125*288bf522SAndroid Build Coastguard Worker  # In case someone turns it off behind our back
126*288bf522SAndroid Build Coastguard Worker  echo ${GC_SLEEP} > /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time
127*288bf522SAndroid Build Coastguard Worker  echo ${GC_TYPE} > /dev/sys/fs/by-name/userdata/gc_urgent
128*288bf522SAndroid Build Coastguard Workerdone
129*288bf522SAndroid Build Coastguard Worker
130*288bf522SAndroid Build Coastguard Worker# It could be a while before the system reboots for the update...
131*288bf522SAndroid Build Coastguard Worker# Leaving on low level GC can help ensure the boot for ota is faster
132*288bf522SAndroid Build Coastguard Worker# If powerhints decides to turn it off, we'll just rely on normal GC
133*288bf522SAndroid Build Coastguard Workerlog -pi -t checkpoint_gc Leaving on GC_URGENT_LOW for userdata
134*288bf522SAndroid Build Coastguard Workerecho ${OLD_SLEEP} > /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time
135*288bf522SAndroid Build Coastguard Workerecho 2 > /dev/sys/fs/by-name/userdata/gc_urgent
136*288bf522SAndroid Build Coastguard Workersync
137*288bf522SAndroid Build Coastguard Worker
138*288bf522SAndroid Build Coastguard Workerprint -u${STATUS_FD} "global_progress 1.0"
139*288bf522SAndroid Build Coastguard Workerexit 0
140