diff options
| -rw-r--r-- | cmds/installd/CacheItem.cpp | 33 | ||||
| -rw-r--r-- | cmds/installd/CacheTracker.cpp | 50 | ||||
| -rw-r--r-- | cmds/installd/CacheTracker.h | 1 | ||||
| -rw-r--r-- | cmds/installd/InstalldNativeService.cpp | 64 | ||||
| -rw-r--r-- | cmds/installd/InstalldNativeService.h | 12 | ||||
| -rw-r--r-- | cmds/installd/utils.h | 3 |
6 files changed, 122 insertions, 41 deletions
diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp index 17eb7ff0e1..515f915b8b 100644 --- a/cmds/installd/CacheItem.cpp +++ b/cmds/installd/CacheItem.cpp @@ -67,6 +67,7 @@ std::string CacheItem::buildPath() { } int CacheItem::purge() { + int res = 0; auto path = buildPath(); if (directory) { FTS *fts; @@ -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 diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp index 4bfc834d86..e293948caa 100644 --- a/cmds/installd/CacheTracker.cpp +++ b/cmds/installd/CacheTracker.cpp @@ -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(); - return; - } + ATRACE_BEGIN("loadStats quota"); + cacheUsed = 0; + if (loadQuotaStats()) { + return; } + ATRACE_END(); ATRACE_BEGIN("loadStats tree"); cacheUsed = 0; @@ -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; diff --git a/cmds/installd/CacheTracker.h b/cmds/installd/CacheTracker.h index 91692d7469..44359b4970 100644 --- a/cmds/installd/CacheTracker.h +++ b/cmds/installd/CacheTracker.h @@ -66,6 +66,7 @@ private: std::vector<std::string> mDataPaths; + bool loadQuotaStats(); void loadItemsFrom(const std::string& path); DISALLOW_COPY_AND_ASSIGN(CacheTracker); diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 49a3b23b52..19dfb8789d 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -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; @@ -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); } @@ -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); @@ -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) { @@ -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; @@ -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()) { @@ -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. @@ -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( diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index 7f73c2ae15..200fc77341 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -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); }; diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h index dd94da9e31..070da84c9e 100644 --- a/cmds/installd/utils.h +++ b/cmds/installd/utils.h @@ -33,6 +33,9 @@ #define MEASURE_DEBUG 0 #define FIXUP_DEBUG 0 +#define BYPASS_QUOTA 0 +#define BYPASS_SDCARDFS 0 + namespace android { namespace installd { |