Use inode numbers for CE storage, fix sizes.
Certain operations, such as clearing/destroying app data, or just
counting on-disk size, require us to know the CE storage directory
of a particular app. To facilitate these operations, offer a method
to get the inode of a CE directory, and accept that inode number
for later operations.
In previous releases, we started installing apps using a new
directory-based layout, where all app code, unpacked native libraries,
and optimized code is bundled together. So now we only have a single
path to measure for code size.
Start measuring both CE and DE storage data usage for apps, and tweak
the reporting so that empty cache/data directories actually show up
as "0 bytes".
Fix bugs in disk usage counting, since st_blksize has no bearing on
the allocated disk space. Also don't double-count "." and ".."
directories when measuring storage.
Bug: 27828915, 27197819
Change-Id: I350b951f5c24165edb253ac663c9aae020c24dc9
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index d84d9f6..878fb2d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -81,11 +81,39 @@
* volume UUID, package name, and user ID. An empty UUID is assumed to be
* internal storage.
*/
-std::string create_data_user_package_path(const char* volume_uuid,
+std::string create_data_user_ce_package_path(const char* volume_uuid,
userid_t user, const char* package_name) {
check_package_name(package_name);
return StringPrintf("%s/%s",
- create_data_user_path(volume_uuid, user).c_str(), package_name);
+ create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
+}
+
+std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
+ const char* package_name, ino_t ce_data_inode) {
+ // For testing purposes, rely on the inode when defined; this could be
+ // optimized to use access() in the future.
+ auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
+ if (ce_data_inode != 0) {
+ auto user_path = create_data_user_ce_path(volume_uuid, user);
+ DIR* dir = opendir(user_path.c_str());
+ if (dir == nullptr) {
+ PLOG(ERROR) << "Failed to opendir " << user_path;
+ return fallback;
+ }
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_ino == ce_data_inode) {
+ closedir(dir);
+ return StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+ }
+ }
+ LOG(WARNING) << "Failed to find inode " << ce_data_inode << " for package " << package_name;
+ closedir(dir);
+ return fallback;
+ } else {
+ return fallback;
+ }
}
std::string create_data_user_de_package_path(const char* volume_uuid,
@@ -102,7 +130,7 @@
return -1;
}
- std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix);
+ std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix);
const char* tmp = _tmp.c_str();
if (strlen(tmp) >= PKG_PATH_MAX) {
path[0] = '\0';
@@ -132,7 +160,7 @@
/**
* Create the path name for user data for a certain userid.
*/
-std::string create_data_user_path(const char* volume_uuid, userid_t userid) {
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
std::string data(create_data_path(volume_uuid));
if (volume_uuid == nullptr) {
if (userid == 0) {