diff options
author | 2017-01-17 16:54:00 +0000 | |
---|---|---|
committer | 2017-01-17 16:54:01 +0000 | |
commit | 36ba03a248e34aa92aaa9667a4fa71c64bea5c23 (patch) | |
tree | 14a1b8f61b9101305bc2e85abdc4e8b7766ba514 | |
parent | 950e3f56964a714f68c6494fb4d045fef927bade (diff) | |
parent | 66b1a12e7a120f85042669bb58f1db864616b506 (diff) |
Merge "Handle devices without quota, speed up lookup."
-rw-r--r-- | cmds/installd/InstalldNativeService.cpp | 100 | ||||
-rw-r--r-- | cmds/installd/InstalldNativeService.h | 8 | ||||
-rw-r--r-- | cmds/installd/binder/android/os/IInstalld.aidl | 2 |
3 files changed, 75 insertions, 35 deletions
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 102359d442..0339086cf0 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -60,6 +60,7 @@ #endif using android::base::StringPrintf; +using std::endl; namespace android { namespace installd { @@ -188,15 +189,22 @@ status_t InstalldNativeService::start() { } status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) { + auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd)); const binder::Status dump_permission = checkPermission(kDump); if (!dump_permission.isOk()) { - const String8 msg(dump_permission.toString8()); - write(fd, msg.string(), msg.size()); + out << dump_permission.toString8() << endl; return PERMISSION_DENIED; } + std::lock_guard<std::recursive_mutex> lock(mLock); + + out << "installd is happy!" << endl << endl; + out << "Devices with quota support:" << endl; + for (const auto& n : mQuotaDevices) { + out << " " << n.first << " = " << n.second << endl; + } + out << endl; + out.flush(); - std::string msg = "installd is happy\n"; - write(fd, msg.c_str(), strlen(msg.c_str())); return NO_ERROR; } @@ -888,28 +896,6 @@ static std::string toString(std::vector<int64_t> values) { } #endif -static std::string findDeviceForUuid(const std::unique_ptr<std::string>& uuid) { - auto path = create_data_path(uuid ? uuid->c_str() : nullptr); - std::ifstream in("/proc/mounts"); - if (!in.is_open()) { - PLOG(ERROR) << "Failed to read mounts"; - return ""; - } - std::string source; - std::string target; - while (!in.eof()) { - std::getline(in, source, ' '); - std::getline(in, target, ' '); - if (target == path) { - return source; - } - // Skip to next line - std::getline(in, source); - } - PLOG(ERROR) << "Failed to resolve block device for " << path; - return ""; -} - static void collectQuotaStats(const std::string& device, int32_t userId, int32_t appId, struct stats* stats, struct stats* extStats ATTRIBUTE_UNUSED) { if (device.empty()) return; @@ -964,11 +950,6 @@ static void collectQuotaStats(const std::string& device, int32_t userId, #endif } -static void collectQuotaStats(const std::unique_ptr<std::string>& uuid, int32_t userId, - int32_t appId, struct stats* stats, struct stats* extStats) { - collectQuotaStats(findDeviceForUuid(uuid), userId, appId, stats, extStats); -} - static void collectManualStats(const std::string& path, struct stats* stats) { DIR *d; int dfd; @@ -1090,6 +1071,11 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri const char* uuid_ = uuid ? uuid->c_str() : nullptr; + auto device = findQuotaDeviceForUuid(uuid); + if (device.empty()) { + flags &= ~FLAG_USE_QUOTA; + } + for (auto packageName : packageNames) { auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str()); calculate_tree_size(obbCodePath, &extStats.codeSize); @@ -1101,7 +1087,7 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri multiuser_get_shared_gid(userId, appId)); } - collectQuotaStats(uuid, userId, appId, &stats, &extStats); + collectQuotaStats(device, userId, appId, &stats, &extStats); } else { for (auto codePath : codePaths) { @@ -1180,6 +1166,11 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str auto obbPath = create_data_path(uuid_) + "/media/obb"; calculate_tree_size(obbPath, &extStats.codeSize); + auto device = findQuotaDeviceForUuid(uuid); + if (device.empty()) { + flags &= ~FLAG_USE_QUOTA; + } + if (flags & FLAG_USE_QUOTA) { calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true); @@ -1205,7 +1196,6 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize, -1, -1, true); - auto device = findDeviceForUuid(uuid); for (auto appId : appIds) { if (appId >= AID_APP_START) { collectQuotaStats(device, userId, appId, &stats, &extStats); @@ -1273,11 +1263,14 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std: int64_t videoSize = 0; int64_t imageSize = 0; + auto device = findQuotaDeviceForUuid(uuid); + if (device.empty()) { + flags &= ~FLAG_USE_QUOTA; + } + if (flags & FLAG_USE_QUOTA) { struct dqblk dq; - auto device = findDeviceForUuid(uuid); - uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW); if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, reinterpret_cast<char*>(&dq)) != 0) { @@ -1776,5 +1769,42 @@ binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath, return res ? ok() : error(); } +binder::Status InstalldNativeService::invalidateMounts() { + ENFORCE_UID(AID_SYSTEM); + std::lock_guard<std::recursive_mutex> lock(mLock); + + mQuotaDevices.clear(); + + std::ifstream in("/proc/mounts"); + if (!in.is_open()) { + return error("Failed to read mounts"); + } + + 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 (source.compare(0, 11, "/dev/block/") == 0) { + if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0, + reinterpret_cast<char*>(&dq)) == 0) { + LOG(DEBUG) << "Found " << source << " with quota"; + mQuotaDevices[target] = source; + } + } + } + return ok(); +} + +std::string InstalldNativeService::findQuotaDeviceForUuid( + const std::unique_ptr<std::string>& uuid) { + auto path = create_data_path(uuid ? uuid->c_str() : nullptr); + return mQuotaDevices[path]; +} + } // namespace installd } // namespace android diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index ec814629c0..0208fb147c 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -22,6 +22,7 @@ #include <unistd.h> #include <vector> +#include <unordered_map> #include <binder/BinderService.h> #include <cutils/multiuser.h> @@ -100,8 +101,15 @@ public: binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet, const std::string& outputPath); + binder::Status invalidateMounts(); + private: std::recursive_mutex mLock; + + /* Map from mount point to underlying device node */ + std::unordered_map<std::string, std::string> mQuotaDevices; + + std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid); }; } // namespace installd diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 6e4d7fa7ab..2f12ea9f37 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -68,4 +68,6 @@ interface IInstalld { @utf8InCpp String outputPath); void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet, @utf8InCpp String outputPath); + + void invalidateMounts(); } |