Loading cmds/installd/CacheItem.cpp +26 −7 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ std::string CacheItem::buildPath() { } int CacheItem::purge() { int res = 0; auto path = buildPath(); if (directory) { FTS *fts; Loading @@ -88,29 +89,47 @@ int CacheItem::purge() { break; case FTS_F: if (p->fts_parent->fts_number) { truncate(p->fts_path, 0); if (truncate(p->fts_path, 0) != 0) { PLOG(WARNING) << "Failed to truncate " << p->fts_path; res = -1; } } else { unlink(p->fts_path); if (unlink(p->fts_path) != 0) { PLOG(WARNING) << "Failed to unlink " << p->fts_path; res = -1; } } break; case FTS_DEFAULT: case FTS_SL: case FTS_SLNONE: unlink(p->fts_path); if (unlink(p->fts_path) != 0) { PLOG(WARNING) << "Failed to unlink " << p->fts_path; res = -1; } break; case FTS_DP: rmdir(p->fts_path); if (rmdir(p->fts_path) != 0) { PLOG(WARNING) << "Failed to rmdir " << p->fts_path; res = -1; } break; } } return 0; } else { if (tombstone) { return truncate(path.c_str(), 0); if (truncate(path.c_str(), 0) != 0) { PLOG(WARNING) << "Failed to truncate " << path; res = -1; } } else { return unlink(path.c_str()); if (unlink(path.c_str()) != 0) { PLOG(WARNING) << "Failed to unlink " << path; res = -1; } } } return res; } } // namespace installd Loading cmds/installd/CacheTracker.cpp +35 −15 Original line number Diff line number Diff line Loading @@ -51,22 +51,12 @@ void CacheTracker::addDataPath(const std::string& dataPath) { } void CacheTracker::loadStats() { int cacheGid = multiuser_get_cache_gid(mUserId, mAppId); if (cacheGid != -1 && !mQuotaDevice.empty()) { ATRACE_BEGIN("loadStats quota"); struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid, reinterpret_cast<char*>(&dq)) != 0) { ATRACE_END(); if (errno != ESRCH) { PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid; } } else { cacheUsed = dq.dqb_curspace; ATRACE_END(); cacheUsed = 0; if (loadQuotaStats()) { return; } } ATRACE_END(); ATRACE_BEGIN("loadStats tree"); cacheUsed = 0; Loading @@ -79,6 +69,36 @@ void CacheTracker::loadStats() { ATRACE_END(); } bool CacheTracker::loadQuotaStats() { int cacheGid = multiuser_get_cache_gid(mUserId, mAppId); int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId); if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) { struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid, reinterpret_cast<char*>(&dq)) != 0) { if (errno != ESRCH) { PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid; } return false; } else { cacheUsed += dq.dqb_curspace; } if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid, reinterpret_cast<char*>(&dq)) != 0) { if (errno != ESRCH) { PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid; } return false; } else { cacheUsed += dq.dqb_curspace; } return true; } else { return false; } } void CacheTracker::loadItemsFrom(const std::string& path) { FTS *fts; FTSENT *p; Loading cmds/installd/CacheTracker.h +1 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ private: std::vector<std::string> mDataPaths; bool loadQuotaStats(); void loadItemsFrom(const std::string& path); DISALLOW_COPY_AND_ASSIGN(CacheTracker); Loading cmds/installd/InstalldNativeService.cpp +49 −15 Original line number Diff line number Diff line Loading @@ -205,15 +205,20 @@ status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */ out << "installd is happy!" << endl; { std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); out << endl << "Devices with quota support:" << endl; for (const auto& n : mQuotaDevices) { std::lock_guard<std::recursive_mutex> lock(mMountsLock); out << endl << "Storage mounts:" << endl; for (const auto& n : mStorageMounts) { out << " " << n.first << " = " << n.second << endl; } out << endl << "Quota reverse mounts:" << endl; for (const auto& n : mQuotaReverseMounts) { out << " " << n.first << " = " << n.second << endl; } } { std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); std::lock_guard<std::recursive_mutex> lock(mQuotasLock); out << endl << "Per-UID cache quotas:" << endl; for (const auto& n : mCacheQuotas) { out << " " << n.first << " = " << n.second << endl; Loading Loading @@ -901,7 +906,7 @@ binder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std: if (delete_dir_contents_and_dir(path, true) != 0) { res = error("Failed to delete " + path); } path = create_data_media_path(uuid_, userId); path = findDataMediaPath(uuid, userId); if (delete_dir_contents_and_dir(path, true) != 0) { res = error("Failed to delete " + path); } Loading Loading @@ -952,13 +957,19 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin FTSENT *p; auto ce_path = create_data_user_ce_path(uuid_, user); auto de_path = create_data_user_de_path(uuid_, user); char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr }; auto media_path = findDataMediaPath(uuid, user) + "/Android/data/"; char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), (char*) media_path.c_str(), nullptr }; if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { return error("Failed to fts_open"); } while ((p = fts_read(fts)) != NULL) { if (p->fts_info == FTS_D && p->fts_level == 1) { uid_t uid = p->fts_statp->st_uid; if (multiuser_get_app_id(uid) == AID_MEDIA_RW) { uid = (multiuser_get_app_id(p->fts_statp->st_gid) - AID_EXT_GID_START) + AID_APP_START; } auto search = trackers.find(uid); if (search != trackers.end()) { search->second->addDataPath(p->fts_path); Loading @@ -967,7 +978,7 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin multiuser_get_user_id(uid), multiuser_get_app_id(uid), device)); tracker->addDataPath(p->fts_path); { std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); std::lock_guard<std::recursive_mutex> lock(mQuotasLock); tracker->cacheQuota = mCacheQuotas[uid]; } if (tracker->cacheQuota == 0) { Loading Loading @@ -1745,7 +1756,7 @@ binder::Status InstalldNativeService::setAppQuota(const std::unique_ptr<std::str int32_t userId, int32_t appId, int64_t cacheQuota) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(uuid); std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); std::lock_guard<std::recursive_mutex> lock(mQuotasLock); int32_t uid = multiuser_get_uid(userId, appId); mCacheQuotas[uid] = cacheQuota; Loading Loading @@ -2219,9 +2230,10 @@ binder::Status InstalldNativeService::reconcileSecondaryDexFile( binder::Status InstalldNativeService::invalidateMounts() { ENFORCE_UID(AID_SYSTEM); std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); std::lock_guard<std::recursive_mutex> lock(mMountsLock); mQuotaDevices.clear(); mStorageMounts.clear(); mQuotaReverseMounts.clear(); std::ifstream in("/proc/mounts"); if (!in.is_open()) { Loading @@ -2231,17 +2243,25 @@ binder::Status InstalldNativeService::invalidateMounts() { std::string source; std::string target; std::string ignored; struct dqblk dq; while (!in.eof()) { std::getline(in, source, ' '); std::getline(in, target, ' '); std::getline(in, ignored); #if !BYPASS_SDCARDFS if (target.compare(0, 21, "/mnt/runtime/default/") == 0) { LOG(DEBUG) << "Found storage mount " << source << " at " << target; mStorageMounts[source] = target; } #endif #if !BYPASS_QUOTA if (source.compare(0, 11, "/dev/block/") == 0) { struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0, reinterpret_cast<char*>(&dq)) == 0) { LOG(DEBUG) << "Found " << source << " with quota"; mQuotaDevices[target] = source; LOG(DEBUG) << "Found quota mount " << source << " at " << target; mQuotaReverseMounts[target] = source; // ext4 only enables DQUOT_USAGE_ENABLED by default, so we // need to kick it again to enable DQUOT_LIMITS_ENABLED. Loading @@ -2255,15 +2275,29 @@ binder::Status InstalldNativeService::invalidateMounts() { } } } #endif } return ok(); } std::string InstalldNativeService::findDataMediaPath( const std::unique_ptr<std::string>& uuid, userid_t userid) { std::lock_guard<std::recursive_mutex> lock(mMountsLock); const char* uuid_ = uuid ? uuid->c_str() : nullptr; auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str()); auto resolved = mStorageMounts[path]; if (resolved.empty()) { LOG(WARNING) << "Failed to find storage mount for " << path; resolved = path; } return StringPrintf("%s/%u", resolved.c_str(), userid); } std::string InstalldNativeService::findQuotaDeviceForUuid( const std::unique_ptr<std::string>& uuid) { std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); std::lock_guard<std::recursive_mutex> lock(mMountsLock); auto path = create_data_path(uuid ? uuid->c_str() : nullptr); return mQuotaDevices[path]; return mQuotaReverseMounts[path]; } binder::Status InstalldNativeService::isQuotaSupported( Loading cmds/installd/InstalldNativeService.h +8 −4 Original line number Diff line number Diff line Loading @@ -121,14 +121,18 @@ public: private: std::recursive_mutex mLock; std::recursive_mutex mQuotaDevicesLock; std::recursive_mutex mCacheQuotasLock; std::recursive_mutex mMountsLock; std::recursive_mutex mQuotasLock; /* Map of all storage mounts from source to target */ std::unordered_map<std::string, std::string> mStorageMounts; /* Map of all quota mounts from target to source */ std::unordered_map<std::string, std::string> mQuotaReverseMounts; /* Map from mount point to underlying device node */ std::unordered_map<std::string, std::string> mQuotaDevices; /* Map from UID to cache quota size */ std::unordered_map<uid_t, int64_t> mCacheQuotas; std::string findDataMediaPath(const std::unique_ptr<std::string>& uuid, userid_t userid); std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid); }; Loading Loading
cmds/installd/CacheItem.cpp +26 −7 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ std::string CacheItem::buildPath() { } int CacheItem::purge() { int res = 0; auto path = buildPath(); if (directory) { FTS *fts; Loading @@ -88,29 +89,47 @@ int CacheItem::purge() { break; case FTS_F: if (p->fts_parent->fts_number) { truncate(p->fts_path, 0); if (truncate(p->fts_path, 0) != 0) { PLOG(WARNING) << "Failed to truncate " << p->fts_path; res = -1; } } else { unlink(p->fts_path); if (unlink(p->fts_path) != 0) { PLOG(WARNING) << "Failed to unlink " << p->fts_path; res = -1; } } break; case FTS_DEFAULT: case FTS_SL: case FTS_SLNONE: unlink(p->fts_path); if (unlink(p->fts_path) != 0) { PLOG(WARNING) << "Failed to unlink " << p->fts_path; res = -1; } break; case FTS_DP: rmdir(p->fts_path); if (rmdir(p->fts_path) != 0) { PLOG(WARNING) << "Failed to rmdir " << p->fts_path; res = -1; } break; } } return 0; } else { if (tombstone) { return truncate(path.c_str(), 0); if (truncate(path.c_str(), 0) != 0) { PLOG(WARNING) << "Failed to truncate " << path; res = -1; } } else { return unlink(path.c_str()); if (unlink(path.c_str()) != 0) { PLOG(WARNING) << "Failed to unlink " << path; res = -1; } } } return res; } } // namespace installd Loading
cmds/installd/CacheTracker.cpp +35 −15 Original line number Diff line number Diff line Loading @@ -51,22 +51,12 @@ void CacheTracker::addDataPath(const std::string& dataPath) { } void CacheTracker::loadStats() { int cacheGid = multiuser_get_cache_gid(mUserId, mAppId); if (cacheGid != -1 && !mQuotaDevice.empty()) { ATRACE_BEGIN("loadStats quota"); struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid, reinterpret_cast<char*>(&dq)) != 0) { ATRACE_END(); if (errno != ESRCH) { PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid; } } else { cacheUsed = dq.dqb_curspace; ATRACE_END(); cacheUsed = 0; if (loadQuotaStats()) { return; } } ATRACE_END(); ATRACE_BEGIN("loadStats tree"); cacheUsed = 0; Loading @@ -79,6 +69,36 @@ void CacheTracker::loadStats() { ATRACE_END(); } bool CacheTracker::loadQuotaStats() { int cacheGid = multiuser_get_cache_gid(mUserId, mAppId); int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId); if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) { struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid, reinterpret_cast<char*>(&dq)) != 0) { if (errno != ESRCH) { PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid; } return false; } else { cacheUsed += dq.dqb_curspace; } if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid, reinterpret_cast<char*>(&dq)) != 0) { if (errno != ESRCH) { PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid; } return false; } else { cacheUsed += dq.dqb_curspace; } return true; } else { return false; } } void CacheTracker::loadItemsFrom(const std::string& path) { FTS *fts; FTSENT *p; Loading
cmds/installd/CacheTracker.h +1 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ private: std::vector<std::string> mDataPaths; bool loadQuotaStats(); void loadItemsFrom(const std::string& path); DISALLOW_COPY_AND_ASSIGN(CacheTracker); Loading
cmds/installd/InstalldNativeService.cpp +49 −15 Original line number Diff line number Diff line Loading @@ -205,15 +205,20 @@ status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */ out << "installd is happy!" << endl; { std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); out << endl << "Devices with quota support:" << endl; for (const auto& n : mQuotaDevices) { std::lock_guard<std::recursive_mutex> lock(mMountsLock); out << endl << "Storage mounts:" << endl; for (const auto& n : mStorageMounts) { out << " " << n.first << " = " << n.second << endl; } out << endl << "Quota reverse mounts:" << endl; for (const auto& n : mQuotaReverseMounts) { out << " " << n.first << " = " << n.second << endl; } } { std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); std::lock_guard<std::recursive_mutex> lock(mQuotasLock); out << endl << "Per-UID cache quotas:" << endl; for (const auto& n : mCacheQuotas) { out << " " << n.first << " = " << n.second << endl; Loading Loading @@ -901,7 +906,7 @@ binder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std: if (delete_dir_contents_and_dir(path, true) != 0) { res = error("Failed to delete " + path); } path = create_data_media_path(uuid_, userId); path = findDataMediaPath(uuid, userId); if (delete_dir_contents_and_dir(path, true) != 0) { res = error("Failed to delete " + path); } Loading Loading @@ -952,13 +957,19 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin FTSENT *p; auto ce_path = create_data_user_ce_path(uuid_, user); auto de_path = create_data_user_de_path(uuid_, user); char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr }; auto media_path = findDataMediaPath(uuid, user) + "/Android/data/"; char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), (char*) media_path.c_str(), nullptr }; if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) { return error("Failed to fts_open"); } while ((p = fts_read(fts)) != NULL) { if (p->fts_info == FTS_D && p->fts_level == 1) { uid_t uid = p->fts_statp->st_uid; if (multiuser_get_app_id(uid) == AID_MEDIA_RW) { uid = (multiuser_get_app_id(p->fts_statp->st_gid) - AID_EXT_GID_START) + AID_APP_START; } auto search = trackers.find(uid); if (search != trackers.end()) { search->second->addDataPath(p->fts_path); Loading @@ -967,7 +978,7 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin multiuser_get_user_id(uid), multiuser_get_app_id(uid), device)); tracker->addDataPath(p->fts_path); { std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); std::lock_guard<std::recursive_mutex> lock(mQuotasLock); tracker->cacheQuota = mCacheQuotas[uid]; } if (tracker->cacheQuota == 0) { Loading Loading @@ -1745,7 +1756,7 @@ binder::Status InstalldNativeService::setAppQuota(const std::unique_ptr<std::str int32_t userId, int32_t appId, int64_t cacheQuota) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID(uuid); std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock); std::lock_guard<std::recursive_mutex> lock(mQuotasLock); int32_t uid = multiuser_get_uid(userId, appId); mCacheQuotas[uid] = cacheQuota; Loading Loading @@ -2219,9 +2230,10 @@ binder::Status InstalldNativeService::reconcileSecondaryDexFile( binder::Status InstalldNativeService::invalidateMounts() { ENFORCE_UID(AID_SYSTEM); std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); std::lock_guard<std::recursive_mutex> lock(mMountsLock); mQuotaDevices.clear(); mStorageMounts.clear(); mQuotaReverseMounts.clear(); std::ifstream in("/proc/mounts"); if (!in.is_open()) { Loading @@ -2231,17 +2243,25 @@ binder::Status InstalldNativeService::invalidateMounts() { std::string source; std::string target; std::string ignored; struct dqblk dq; while (!in.eof()) { std::getline(in, source, ' '); std::getline(in, target, ' '); std::getline(in, ignored); #if !BYPASS_SDCARDFS if (target.compare(0, 21, "/mnt/runtime/default/") == 0) { LOG(DEBUG) << "Found storage mount " << source << " at " << target; mStorageMounts[source] = target; } #endif #if !BYPASS_QUOTA if (source.compare(0, 11, "/dev/block/") == 0) { struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0, reinterpret_cast<char*>(&dq)) == 0) { LOG(DEBUG) << "Found " << source << " with quota"; mQuotaDevices[target] = source; LOG(DEBUG) << "Found quota mount " << source << " at " << target; mQuotaReverseMounts[target] = source; // ext4 only enables DQUOT_USAGE_ENABLED by default, so we // need to kick it again to enable DQUOT_LIMITS_ENABLED. Loading @@ -2255,15 +2275,29 @@ binder::Status InstalldNativeService::invalidateMounts() { } } } #endif } return ok(); } std::string InstalldNativeService::findDataMediaPath( const std::unique_ptr<std::string>& uuid, userid_t userid) { std::lock_guard<std::recursive_mutex> lock(mMountsLock); const char* uuid_ = uuid ? uuid->c_str() : nullptr; auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str()); auto resolved = mStorageMounts[path]; if (resolved.empty()) { LOG(WARNING) << "Failed to find storage mount for " << path; resolved = path; } return StringPrintf("%s/%u", resolved.c_str(), userid); } std::string InstalldNativeService::findQuotaDeviceForUuid( const std::unique_ptr<std::string>& uuid) { std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock); std::lock_guard<std::recursive_mutex> lock(mMountsLock); auto path = create_data_path(uuid ? uuid->c_str() : nullptr); return mQuotaDevices[path]; return mQuotaReverseMounts[path]; } binder::Status InstalldNativeService::isQuotaSupported( Loading
cmds/installd/InstalldNativeService.h +8 −4 Original line number Diff line number Diff line Loading @@ -121,14 +121,18 @@ public: private: std::recursive_mutex mLock; std::recursive_mutex mQuotaDevicesLock; std::recursive_mutex mCacheQuotasLock; std::recursive_mutex mMountsLock; std::recursive_mutex mQuotasLock; /* Map of all storage mounts from source to target */ std::unordered_map<std::string, std::string> mStorageMounts; /* Map of all quota mounts from target to source */ std::unordered_map<std::string, std::string> mQuotaReverseMounts; /* Map from mount point to underlying device node */ std::unordered_map<std::string, std::string> mQuotaDevices; /* Map from UID to cache quota size */ std::unordered_map<uid_t, int64_t> mCacheQuotas; std::string findDataMediaPath(const std::unique_ptr<std::string>& uuid, userid_t userid); std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid); }; Loading