IdleMaint.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * Copyright (C) 2015 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "IdleMaint.h"
  17. #include "FileDeviceUtils.h"
  18. #include "Utils.h"
  19. #include "VolumeManager.h"
  20. #include "model/PrivateVolume.h"
  21. #include <thread>
  22. #include <android-base/chrono_utils.h>
  23. #include <android-base/file.h>
  24. #include <android-base/logging.h>
  25. #include <android-base/stringprintf.h>
  26. #include <android-base/strings.h>
  27. #include <android/hardware/health/storage/1.0/IStorage.h>
  28. #include <fs_mgr.h>
  29. #include <hardware_legacy/power.h>
  30. #include <private/android_filesystem_config.h>
  31. #include <dirent.h>
  32. #include <fcntl.h>
  33. #include <sys/mount.h>
  34. #include <sys/stat.h>
  35. #include <sys/types.h>
  36. #include <sys/wait.h>
  37. using android::base::Basename;
  38. using android::base::ReadFileToString;
  39. using android::base::Realpath;
  40. using android::base::StringPrintf;
  41. using android::base::Timer;
  42. using android::base::WriteStringToFile;
  43. using android::fs_mgr::Fstab;
  44. using android::fs_mgr::ReadDefaultFstab;
  45. using android::hardware::Return;
  46. using android::hardware::Void;
  47. using android::hardware::health::storage::V1_0::IStorage;
  48. using android::hardware::health::storage::V1_0::IGarbageCollectCallback;
  49. using android::hardware::health::storage::V1_0::Result;
  50. namespace android {
  51. namespace vold {
  52. enum class PathTypes {
  53. kMountPoint = 1,
  54. kBlkDevice,
  55. };
  56. enum class IdleMaintStats {
  57. kStopped = 1,
  58. kRunning,
  59. kAbort,
  60. };
  61. static const char* kWakeLock = "IdleMaint";
  62. static const int DIRTY_SEGMENTS_THRESHOLD = 100;
  63. /*
  64. * Timing policy:
  65. * 1. F2FS_GC = 7 mins
  66. * 2. Trim = 1 min
  67. * 3. Dev GC = 2 mins
  68. */
  69. static const int GC_TIMEOUT_SEC = 420;
  70. static const int DEVGC_TIMEOUT_SEC = 120;
  71. static IdleMaintStats idle_maint_stat(IdleMaintStats::kStopped);
  72. static std::condition_variable cv_abort, cv_stop;
  73. static std::mutex cv_m;
  74. static void addFromVolumeManager(std::list<std::string>* paths, PathTypes path_type) {
  75. VolumeManager* vm = VolumeManager::Instance();
  76. std::list<std::string> privateIds;
  77. vm->listVolumes(VolumeBase::Type::kPrivate, privateIds);
  78. for (const auto& id : privateIds) {
  79. PrivateVolume* vol = static_cast<PrivateVolume*>(vm->findVolume(id).get());
  80. if (vol != nullptr && vol->getState() == VolumeBase::State::kMounted) {
  81. if (path_type == PathTypes::kMountPoint) {
  82. paths->push_back(vol->getPath());
  83. } else if (path_type == PathTypes::kBlkDevice) {
  84. std::string gc_path;
  85. const std::string& fs_type = vol->getFsType();
  86. if (fs_type == "f2fs" && (Realpath(vol->getRawDmDevPath(), &gc_path) ||
  87. Realpath(vol->getRawDevPath(), &gc_path))) {
  88. paths->push_back(std::string("/sys/fs/") + fs_type + "/" + Basename(gc_path));
  89. }
  90. }
  91. }
  92. }
  93. }
  94. static void addFromFstab(std::list<std::string>* paths, PathTypes path_type) {
  95. Fstab fstab;
  96. ReadDefaultFstab(&fstab);
  97. std::string previous_mount_point;
  98. for (const auto& entry : fstab) {
  99. // Skip raw partitions.
  100. if (entry.fs_type == "emmc" || entry.fs_type == "mtd") {
  101. continue;
  102. }
  103. // Skip read-only filesystems
  104. if (entry.flags & MS_RDONLY) {
  105. continue;
  106. }
  107. if (entry.fs_mgr_flags.vold_managed) {
  108. continue; // Should we trim fat32 filesystems?
  109. }
  110. if (entry.fs_mgr_flags.no_trim) {
  111. continue;
  112. }
  113. // Skip the multi-type partitions, which are required to be following each other.
  114. // See fs_mgr.c's mount_with_alternatives().
  115. if (entry.mount_point == previous_mount_point) {
  116. continue;
  117. }
  118. if (path_type == PathTypes::kMountPoint) {
  119. paths->push_back(entry.mount_point);
  120. } else if (path_type == PathTypes::kBlkDevice) {
  121. std::string gc_path;
  122. if (entry.fs_type == "f2fs" &&
  123. Realpath(android::vold::BlockDeviceForPath(entry.mount_point + "/"), &gc_path)) {
  124. paths->push_back("/sys/fs/" + entry.fs_type + "/" + Basename(gc_path));
  125. }
  126. }
  127. previous_mount_point = entry.mount_point;
  128. }
  129. }
  130. void Trim(const android::sp<android::os::IVoldTaskListener>& listener) {
  131. acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
  132. // Collect both fstab and vold volumes
  133. std::list<std::string> paths;
  134. addFromFstab(&paths, PathTypes::kMountPoint);
  135. addFromVolumeManager(&paths, PathTypes::kMountPoint);
  136. for (const auto& path : paths) {
  137. LOG(DEBUG) << "Starting trim of " << path;
  138. android::os::PersistableBundle extras;
  139. extras.putString(String16("path"), String16(path.c_str()));
  140. int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
  141. if (fd < 0) {
  142. PLOG(WARNING) << "Failed to open " << path;
  143. if (listener) {
  144. listener->onStatus(-1, extras);
  145. }
  146. continue;
  147. }
  148. struct fstrim_range range;
  149. memset(&range, 0, sizeof(range));
  150. range.len = ULLONG_MAX;
  151. nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
  152. if (ioctl(fd, FITRIM, &range)) {
  153. PLOG(WARNING) << "Trim failed on " << path;
  154. if (listener) {
  155. listener->onStatus(-1, extras);
  156. }
  157. } else {
  158. nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start;
  159. LOG(INFO) << "Trimmed " << range.len << " bytes on " << path << " in "
  160. << nanoseconds_to_milliseconds(time) << "ms";
  161. extras.putLong(String16("bytes"), range.len);
  162. extras.putLong(String16("time"), time);
  163. if (listener) {
  164. listener->onStatus(0, extras);
  165. }
  166. }
  167. close(fd);
  168. }
  169. if (listener) {
  170. android::os::PersistableBundle extras;
  171. listener->onFinished(0, extras);
  172. }
  173. release_wake_lock(kWakeLock);
  174. }
  175. static bool waitForGc(const std::list<std::string>& paths) {
  176. std::unique_lock<std::mutex> lk(cv_m, std::defer_lock);
  177. bool stop = false, aborted = false;
  178. Timer timer;
  179. while (!stop && !aborted) {
  180. stop = true;
  181. for (const auto& path : paths) {
  182. std::string dirty_segments;
  183. if (!ReadFileToString(path + "/dirty_segments", &dirty_segments)) {
  184. PLOG(WARNING) << "Reading dirty_segments failed in " << path;
  185. continue;
  186. }
  187. if (std::stoi(dirty_segments) > DIRTY_SEGMENTS_THRESHOLD) {
  188. stop = false;
  189. break;
  190. }
  191. }
  192. if (stop) break;
  193. if (timer.duration() >= std::chrono::seconds(GC_TIMEOUT_SEC)) {
  194. LOG(WARNING) << "GC timeout";
  195. break;
  196. }
  197. lk.lock();
  198. aborted =
  199. cv_abort.wait_for(lk, 10s, [] { return idle_maint_stat == IdleMaintStats::kAbort; });
  200. lk.unlock();
  201. }
  202. return aborted;
  203. }
  204. static int startGc(const std::list<std::string>& paths) {
  205. for (const auto& path : paths) {
  206. LOG(DEBUG) << "Start GC on " << path;
  207. if (!WriteStringToFile("1", path + "/gc_urgent")) {
  208. PLOG(WARNING) << "Start GC failed on " << path;
  209. }
  210. }
  211. return android::OK;
  212. }
  213. static int stopGc(const std::list<std::string>& paths) {
  214. for (const auto& path : paths) {
  215. LOG(DEBUG) << "Stop GC on " << path;
  216. if (!WriteStringToFile("0", path + "/gc_urgent")) {
  217. PLOG(WARNING) << "Stop GC failed on " << path;
  218. }
  219. }
  220. return android::OK;
  221. }
  222. static void runDevGcFstab(void) {
  223. Fstab fstab;
  224. ReadDefaultFstab(&fstab);
  225. std::string path;
  226. for (const auto& entry : fstab) {
  227. if (!entry.sysfs_path.empty()) {
  228. path = entry.sysfs_path;
  229. break;
  230. }
  231. }
  232. if (path.empty()) {
  233. return;
  234. }
  235. path = path + "/manual_gc";
  236. Timer timer;
  237. LOG(DEBUG) << "Start Dev GC on " << path;
  238. while (1) {
  239. std::string require;
  240. if (!ReadFileToString(path, &require)) {
  241. PLOG(WARNING) << "Reading manual_gc failed in " << path;
  242. break;
  243. }
  244. require = android::base::Trim(require);
  245. if (require == "" || require == "off" || require == "disabled") {
  246. LOG(DEBUG) << "No more to do Dev GC";
  247. break;
  248. }
  249. LOG(DEBUG) << "Trigger Dev GC on " << path;
  250. if (!WriteStringToFile("1", path)) {
  251. PLOG(WARNING) << "Start Dev GC failed on " << path;
  252. break;
  253. }
  254. if (timer.duration() >= std::chrono::seconds(DEVGC_TIMEOUT_SEC)) {
  255. LOG(WARNING) << "Dev GC timeout";
  256. break;
  257. }
  258. sleep(2);
  259. }
  260. LOG(DEBUG) << "Stop Dev GC on " << path;
  261. if (!WriteStringToFile("0", path)) {
  262. PLOG(WARNING) << "Stop Dev GC failed on " << path;
  263. }
  264. return;
  265. }
  266. class GcCallback : public IGarbageCollectCallback {
  267. public:
  268. Return<void> onFinish(Result result) override {
  269. std::unique_lock<std::mutex> lock(mMutex);
  270. mFinished = true;
  271. mResult = result;
  272. lock.unlock();
  273. mCv.notify_all();
  274. return Void();
  275. }
  276. void wait(uint64_t seconds) {
  277. std::unique_lock<std::mutex> lock(mMutex);
  278. mCv.wait_for(lock, std::chrono::seconds(seconds), [this] { return mFinished; });
  279. if (!mFinished) {
  280. LOG(WARNING) << "Dev GC on HAL timeout";
  281. } else if (mResult != Result::SUCCESS) {
  282. LOG(WARNING) << "Dev GC on HAL failed with " << toString(mResult);
  283. } else {
  284. LOG(INFO) << "Dev GC on HAL successful";
  285. }
  286. }
  287. private:
  288. std::mutex mMutex;
  289. std::condition_variable mCv;
  290. bool mFinished{false};
  291. Result mResult{Result::UNKNOWN_ERROR};
  292. };
  293. static void runDevGcOnHal(sp<IStorage> service) {
  294. LOG(DEBUG) << "Start Dev GC on HAL";
  295. sp<GcCallback> cb = new GcCallback();
  296. auto ret = service->garbageCollect(DEVGC_TIMEOUT_SEC, cb);
  297. if (!ret.isOk()) {
  298. LOG(WARNING) << "Cannot start Dev GC on HAL: " << ret.description();
  299. return;
  300. }
  301. cb->wait(DEVGC_TIMEOUT_SEC);
  302. }
  303. static void runDevGc(void) {
  304. auto service = IStorage::getService();
  305. if (service != nullptr) {
  306. runDevGcOnHal(service);
  307. } else {
  308. // fallback to legacy code path
  309. runDevGcFstab();
  310. }
  311. }
  312. int RunIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener) {
  313. std::unique_lock<std::mutex> lk(cv_m);
  314. if (idle_maint_stat != IdleMaintStats::kStopped) {
  315. LOG(DEBUG) << "idle maintenance is already running";
  316. if (listener) {
  317. android::os::PersistableBundle extras;
  318. listener->onFinished(0, extras);
  319. }
  320. return android::OK;
  321. }
  322. idle_maint_stat = IdleMaintStats::kRunning;
  323. lk.unlock();
  324. LOG(DEBUG) << "idle maintenance started";
  325. acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
  326. std::list<std::string> paths;
  327. addFromFstab(&paths, PathTypes::kBlkDevice);
  328. addFromVolumeManager(&paths, PathTypes::kBlkDevice);
  329. startGc(paths);
  330. bool gc_aborted = waitForGc(paths);
  331. stopGc(paths);
  332. lk.lock();
  333. idle_maint_stat = IdleMaintStats::kStopped;
  334. lk.unlock();
  335. cv_stop.notify_one();
  336. if (!gc_aborted) {
  337. Trim(nullptr);
  338. runDevGc();
  339. }
  340. if (listener) {
  341. android::os::PersistableBundle extras;
  342. listener->onFinished(0, extras);
  343. }
  344. LOG(DEBUG) << "idle maintenance completed";
  345. release_wake_lock(kWakeLock);
  346. return android::OK;
  347. }
  348. int AbortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener) {
  349. acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock);
  350. std::unique_lock<std::mutex> lk(cv_m);
  351. if (idle_maint_stat != IdleMaintStats::kStopped) {
  352. idle_maint_stat = IdleMaintStats::kAbort;
  353. lk.unlock();
  354. cv_abort.notify_one();
  355. lk.lock();
  356. LOG(DEBUG) << "aborting idle maintenance";
  357. cv_stop.wait(lk, [] { return idle_maint_stat == IdleMaintStats::kStopped; });
  358. }
  359. lk.unlock();
  360. if (listener) {
  361. android::os::PersistableBundle extras;
  362. listener->onFinished(0, extras);
  363. }
  364. release_wake_lock(kWakeLock);
  365. LOG(DEBUG) << "idle maintenance stopped";
  366. return android::OK;
  367. }
  368. } // namespace vold
  369. } // namespace android