From 7bf5b9532e192e846be3a31f28171cdba0f3c830 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 19 Jan 2017 09:21:36 -0700 Subject: [PATCH] Measure external storage using new GIDs. We just defined a new range of GIDs that will be used to mark per-app data files stored on external storage, so start measuring them. Also measure all OBB files using another new GID that was defined. Note that we're relying on the per-app cache GIDs to track cache usage on *both* internal and external storage, which means that stats and extStats won't always add up. (The framework already combines these values together, and we didn't want to waste precious GID space on explicitly tracking cache files on external storage.) Test: builds, boots Bug: 27948817, 34263266 Change-Id: Ife087df299ff8ee1a75fce1e39b4b737cf9375d5 --- cmds/installd/InstalldNativeService.cpp | 113 ++++++++++++++++++++++++++------ cmds/installd/utils.h | 1 - 2 files changed, 92 insertions(+), 22 deletions(-) diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 9a984b433b..914eaaee66 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -1028,7 +1028,7 @@ static std::string toString(std::vector values) { #endif static void collectQuotaStats(const std::string& device, int32_t userId, - int32_t appId, struct stats* stats, struct stats* extStats ATTRIBUTE_UNUSED) { + int32_t appId, struct stats* stats, struct stats* extStats) { if (device.empty()) return; struct dqblk dq; @@ -1055,13 +1055,28 @@ static void collectQuotaStats(const std::string& device, int32_t userId, } } else { #if MEASURE_DEBUG - LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace; + LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace; #endif stats->cacheSize += dq.dqb_curspace; } } - int sharedGid = multiuser_get_shared_app_gid(uid); + int extGid = multiuser_get_ext_gid(userId, appId); + if (extGid != -1) { + if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid, + reinterpret_cast(&dq)) != 0) { + if (errno != ESRCH) { + PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid; + } + } else { +#if MEASURE_DEBUG + LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace; +#endif + extStats->dataSize += dq.dqb_curspace; + } + } + + int sharedGid = multiuser_get_shared_gid(userId, appId); if (sharedGid != -1) { if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid, reinterpret_cast(&dq)) != 0) { @@ -1070,15 +1085,11 @@ static void collectQuotaStats(const std::string& device, int32_t userId, } } else { #if MEASURE_DEBUG - LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace; + LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace; #endif stats->codeSize += dq.dqb_curspace; } } - -#if MEASURE_EXTERNAL - // TODO: measure using external GIDs -#endif } static void collectManualStats(const std::string& path, struct stats* stats) { @@ -1164,6 +1175,40 @@ static void collectManualStatsForUser(const std::string& path, struct stats* sta closedir(d); } +static void collectManualExternalStatsForUser(const std::string& path, struct stats* stats) { + FTS *fts; + FTSENT *p; + char *argv[] = { (char*) path.c_str(), nullptr }; + if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) { + PLOG(ERROR) << "Failed to fts_open " << path; + return; + } + while ((p = fts_read(fts)) != NULL) { + switch (p->fts_info) { + case FTS_D: + if (p->fts_level == 4 + && !strcmp(p->fts_name, "cache") + && !strcmp(p->fts_parent->fts_parent->fts_name, "data") + && !strcmp(p->fts_parent->fts_parent->fts_parent->fts_name, "Android")) { + p->fts_number = 1; + } + p->fts_number = p->fts_parent->fts_number; + // Fall through to count the directory + case FTS_DEFAULT: + case FTS_F: + case FTS_SL: + case FTS_SLNONE: + int64_t size = (p->fts_statp->st_blocks * 512); + if (p->fts_number == 1) { + stats->cacheSize += size; + } + stats->dataSize += size; + break; + } + } + fts_close(fts); +} + binder::Status InstalldNativeService::getAppSize(const std::unique_ptr& uuid, const std::vector& packageNames, int32_t userId, int32_t flags, int32_t appId, const std::vector& ceDataInodes, @@ -1250,14 +1295,12 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptrc_str() : nullptr; - ATRACE_BEGIN("obb"); - auto obbPath = create_data_path(uuid_) + "/media/obb"; - calculate_tree_size(obbPath, &extStats.codeSize); - ATRACE_END(); - auto device = findQuotaDeviceForUuid(uuid); if (device.empty()) { flags &= ~FLAG_USE_QUOTA; } if (flags & FLAG_USE_QUOTA) { + struct dqblk dq; + + ATRACE_BEGIN("obb"); + if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB, + reinterpret_cast(&dq)) != 0) { + if (errno != ESRCH) { + PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << AID_MEDIA_OBB; + } + } else { +#if MEASURE_DEBUG + LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace; +#endif + extStats.codeSize += dq.dqb_curspace; + } + ATRACE_END(); + ATRACE_BEGIN("code"); calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true); ATRACE_END(); @@ -1335,11 +1389,20 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr(&dq)) != 0) { + if (errno != ESRCH) { + PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid; + } + } else { +#if MEASURE_DEBUG + LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace; #endif + extStats.dataSize += dq.dqb_curspace; + } + ATRACE_END(); ATRACE_BEGIN("dalvik"); calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize, @@ -1360,6 +1423,11 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr #define MEASURE_DEBUG 0 -#define MEASURE_EXTERNAL 0 namespace android { namespace installd { -- 2.11.0