Offer to measure disk stats using quotas.
Now we're getting somewhere! This CL starts using quotactl() to read
UID/GID quota statistics when called with FLAG_USE_QUOTA, otherwise
it continues using the old heavy-weight traversal for calculation.
We now set the recently defined per-app GID used for identifying
cached data, and we use the sticky GID bit on cache directories to
ensure that newly created data inherits the GID for tracking
purposes. For any existing apps during an upgrade, an initial
bootstrapping case will recursively set this new GID.
This change also shuffles around a bunch of the tedious manual
accounting logic so that we exactly match the new quota statistics.
Test: builds, boots, quota stats match manual stats
Bug: 27948817
Change-Id: I8512c3193ce698f197a3f446e625d6a1c74e7649
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 37e303d..e1a59d4 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -18,6 +18,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <fts.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -198,6 +199,12 @@
return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
}
+std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
+ const char* data_type, const char* package_name) {
+ return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(),
+ data_type, package_name);
+}
+
std::string create_data_misc_legacy_path(userid_t userid) {
return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
}
@@ -216,6 +223,14 @@
return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name);
}
+std::string create_data_dalvik_cache_path() {
+ return "/data/dalvik-cache";
+}
+
+std::string create_data_misc_foreign_dex_path(userid_t userid) {
+ return StringPrintf("/data/misc/profiles/cur/%d/foreign-dex", userid);
+}
+
// Keep profile paths in sync with ActivityThread.
constexpr const char* PRIMARY_PROFILE_NAME = "primary.prof";
@@ -255,6 +270,38 @@
return users;
}
+int calculate_tree_size(const std::string& path, int64_t* size,
+ gid_t include_gid, gid_t exclude_gid) {
+ FTS *fts;
+ FTSENT *p;
+ char *argv[] = { (char*) path.c_str(), nullptr };
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "Failed to fts_open " << path;
+ }
+ return -1;
+ }
+ while ((p = fts_read(fts)) != NULL) {
+ switch (p->fts_info) {
+ case FTS_D:
+ case FTS_DEFAULT:
+ case FTS_F:
+ case FTS_SL:
+ case FTS_SLNONE:
+ if (include_gid != 0 && p->fts_statp->st_gid != include_gid) {
+ break;
+ }
+ if (exclude_gid != 0 && p->fts_statp->st_gid == exclude_gid) {
+ break;
+ }
+ *size += (p->fts_statp->st_blocks * 512);
+ break;
+ }
+ }
+ fts_close(fts);
+ return 0;
+}
+
int create_move_path(char path[PKG_PATH_MAX],
const char* pkgname,
const char* leaf,