diff --git a/IdleMaint.cpp b/IdleMaint.cpp index b1565aa..d0a3a4c 100644 --- a/IdleMaint.cpp +++ b/IdleMaint.cpp @@ -530,9 +530,10 @@ int32_t GetStorageLifeTime() { } void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate, - float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime) { + float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime, + int32_t targetDirtyRatio) { std::list paths; - bool needGC = true; + bool needGC = false; int32_t sleepTime; addFromFstab(&paths, PathTypes::kBlkDevice, true); @@ -575,25 +576,36 @@ void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float int32_t reservedBlocks = std::stoi(ovpSegmentsStr) + std::stoi(reservedBlocksStr); freeSegments = freeSegments > reservedBlocks ? freeSegments - reservedBlocks : 0; - neededSegments *= reclaimWeight; - if (freeSegments >= neededSegments) { - LOG(INFO) << "Enough free segments: " << freeSegments - << ", needed segments: " << neededSegments; - needGC = false; - } else if (freeSegments + dirtySegments < minSegmentThreshold) { + int32_t totalSegments = freeSegments + dirtySegments; + int32_t finalTargetSegments = 0; + + if (totalSegments < minSegmentThreshold) { LOG(INFO) << "The sum of free segments: " << freeSegments - << ", dirty segments: " << dirtySegments << " is under " << minSegmentThreshold; - needGC = false; + << ", dirty segments: " << dirtySegments << " is under " << minSegmentThreshold; } else { - neededSegments -= freeSegments; - neededSegments = std::min(neededSegments, (int32_t)(dirtySegments * dirtyReclaimRate)); - if (neededSegments == 0) { - LOG(INFO) << "Low dirty segments: " << dirtySegments; - needGC = false; + int32_t dirtyRatio = dirtySegments * 100 / totalSegments; + int32_t neededForTargetRatio = + (dirtyRatio > targetDirtyRatio) + ? totalSegments * (dirtyRatio - targetDirtyRatio) / 100 + : 0; + neededSegments *= reclaimWeight; + neededSegments = (neededSegments > freeSegments) ? neededSegments - freeSegments : 0; + + finalTargetSegments = std::max(neededSegments, neededForTargetRatio); + if (finalTargetSegments == 0) { + LOG(INFO) << "Enough free segments: " << freeSegments; } else { - sleepTime = gcPeriod * ONE_MINUTE_IN_MS / neededSegments; - if (sleepTime < minGCSleepTime) { - sleepTime = minGCSleepTime; + finalTargetSegments = + std::min(finalTargetSegments, (int32_t)(dirtySegments * dirtyReclaimRate)); + if (finalTargetSegments == 0) { + LOG(INFO) << "Low dirty segments: " << dirtySegments; + } else if (neededSegments >= neededForTargetRatio) { + LOG(INFO) << "Trigger GC, because of needed segments exceeding free segments"; + needGC = true; + } else { + LOG(INFO) << "Trigger GC for target dirty ratio diff of: " + << dirtyRatio - targetDirtyRatio; + needGC = true; } } } @@ -605,6 +617,11 @@ void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float return; } + sleepTime = gcPeriod * ONE_MINUTE_IN_MS / finalTargetSegments; + if (sleepTime < minGCSleepTime) { + sleepTime = minGCSleepTime; + } + if (!WriteStringToFile(std::to_string(sleepTime), gcSleepTimePath)) { PLOG(WARNING) << "Writing failed in " << gcSleepTimePath; return; @@ -616,8 +633,8 @@ void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float } LOG(INFO) << "Successfully set gc urgent mode: " - << "free segments: " << freeSegments << ", reclaim target: " << neededSegments - << ", sleep time: " << sleepTime; + << "free segments: " << freeSegments << ", reclaim target: " << finalTargetSegments + << ", sleep time: " << sleepTime; } static int32_t getLifeTimeWrite() { diff --git a/IdleMaint.h b/IdleMaint.h index e94f853..a28cde2 100644 --- a/IdleMaint.h +++ b/IdleMaint.h @@ -27,7 +27,8 @@ int RunIdleMaint(bool needGC, const android::sp& int AbortIdleMaint(const android::sp& listener); int32_t GetStorageLifeTime(); void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate, - float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime); + float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime, + int32_t targetDirtyRatio); void RefreshLatestWrite(); int32_t GetWriteAmount(); diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 1284158..ea2c98c 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -495,12 +495,13 @@ binder::Status VoldNativeService::getStorageLifeTime(int32_t* _aidl_return) { binder::Status VoldNativeService::setGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate, float reclaimWeight, - int32_t gcPeriod, int32_t minGCSleepTime) { + int32_t gcPeriod, int32_t minGCSleepTime, + int32_t targetDirtyRatio) { ENFORCE_SYSTEM_OR_ROOT; ACQUIRE_LOCK; SetGCUrgentPace(neededSegments, minSegmentThreshold, dirtyReclaimRate, reclaimWeight, gcPeriod, - minGCSleepTime); + minGCSleepTime, targetDirtyRatio); return Ok(); } diff --git a/VoldNativeService.h b/VoldNativeService.h index 50ef4e3..37a988b 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -91,7 +91,7 @@ class VoldNativeService : public BinderService, public os::Bn binder::Status getStorageLifeTime(int32_t* _aidl_return); binder::Status setGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate, float reclaimWeight, int32_t gcPeriod, - int32_t minGCSleepTime); + int32_t minGCSleepTime, int32_t targetDirtyRatio); binder::Status refreshLatestWrite(); binder::Status getWriteAmount(int32_t* _aidl_return); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index 8422efb..77478d9 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -69,7 +69,8 @@ interface IVold { int getStorageLifeTime(); void setGCUrgentPace(int neededSegments, int minSegmentThreshold, float dirtyReclaimRate, float reclaimWeight, - int gcPeriod, int minGCSleepTime); + int gcPeriod, int minGCSleepTime, + int targetDirtyRatio); void refreshLatestWrite(); int getWriteAmount();