Skip to content

Commit

Permalink
Add vdc volume getStorageSize
Browse files Browse the repository at this point in the history
StorageStatsManager.getTotalBytes currently takes the size of /data and
rounds up to known probable sizes to guess the size of internal storage.
This is not always correct.

Instead, find the device /data is on and get the size of that device.
This should give a more accurate answer.

Bug: 295358118
Test: vdc volume getStorageSize returns storage size
(cherry picked from https://android-review.googlesource.com/q/commit:d73dfd4ab0ff4cbf704034750b2a25832da7fb0c)
Merged-In: I907892041b1ce2cd72092a9877ac34c12bf3f254
Change-Id: I907892041b1ce2cd72092a9877ac34c12bf3f254
(cherry picked from commit 24b7d2d)
  • Loading branch information
PaulLawrenceGoogle authored and Aleksandr Lukin committed Aug 30, 2023
1 parent b3fe942 commit 29ab036
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 0 deletions.
5 changes: 5 additions & 0 deletions VoldNativeService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -930,5 +930,10 @@ binder::Status VoldNativeService::destroyDsuMetadataKey(const std::string& dsuSl
return translateBool(destroy_dsu_metadata_key(dsuSlot));
}

binder::Status VoldNativeService::getStorageSize(int64_t* storageSize) {
ENFORCE_SYSTEM_OR_ROOT;
return translate(GetStorageSize(storageSize));
}

} // namespace vold
} // namespace android
2 changes: 2 additions & 0 deletions VoldNativeService.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ class VoldNativeService : public BinderService<VoldNativeService>, public os::Bn
binder::Status bindMount(const std::string& sourceDir, const std::string& targetDir) override;

binder::Status destroyDsuMetadataKey(const std::string& dsuSlot) override;

binder::Status getStorageSize(int64_t* storageSize) override;
};

} // namespace vold
Expand Down
67 changes: 67 additions & 0 deletions VolumeManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <linux/kdev_t.h>

#include <ApexProperties.sysprop.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
Expand All @@ -53,6 +54,7 @@
#include <private/android_filesystem_config.h>

#include <fscrypt/fscrypt.h>
#include <libdm/dm.h>

#include "AppFuseUtil.h"
#include "FsCrypt.h"
Expand Down Expand Up @@ -1196,3 +1198,68 @@ int VolumeManager::unmountAppFuse(uid_t uid, int mountId) {
int VolumeManager::openAppFuseFile(uid_t uid, int mountId, int fileId, int flags) {
return android::vold::OpenAppFuseFile(uid, mountId, fileId, flags);
}

android::status_t android::vold::GetStorageSize(int64_t* storageSize) {
// Start with the /data mount point from fs_mgr
auto entry = android::fs_mgr::GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
if (entry == nullptr) {
LOG(ERROR) << "No mount point entry for " << DATA_MNT_POINT;
return EINVAL;
}

// Follow any symbolic links
std::string blkDevice = entry->blk_device;
std::string dataDevice;
if (!android::base::Realpath(blkDevice, &dataDevice)) {
dataDevice = blkDevice;
}

// Handle mapped volumes.
auto& dm = android::dm::DeviceMapper::Instance();
for (;;) {
auto parent = dm.GetParentBlockDeviceByPath(dataDevice);
if (!parent.has_value()) break;
dataDevice = *parent;
}

// Get the potential /sys/block entry
std::size_t leaf = dataDevice.rfind('/');
if (leaf == std::string::npos) {
LOG(ERROR) << "data device " << dataDevice << " is not a path";
return EINVAL;
}
if (dataDevice.substr(0, leaf) != "/dev/block") {
LOG(ERROR) << "data device " << dataDevice << " is not a block device";
return EINVAL;
}
std::string sysfs = std::string() + "/sys/block/" + dataDevice.substr(leaf + 1);

// Look for a directory in /sys/block containing size where the name is a shortened
// version of the name we now have
// Typically we start with something like /sys/block/sda2, and we want /sys/block/sda
// Note that this directory only contains actual disks, not partitions, so this is
// not going to find anything other than the disks
std::string size;
std::string sizeFile;
for (std::string sysfsDir = sysfs;; sysfsDir = sysfsDir.substr(0, sysfsDir.size() - 1)) {
if (sysfsDir.back() == '/') {
LOG(ERROR) << "Could not find valid block device from " << sysfs;
return EINVAL;
}
sizeFile = sysfsDir + "/size";
if (android::base::ReadFileToString(sizeFile, &size, true)) {
break;
}
}

// Read the size file and be done
std::stringstream ssSize(size);
ssSize >> *storageSize;
if (ssSize.fail()) {
LOG(ERROR) << sizeFile << " cannot be read as an integer";
return EINVAL;
}

*storageSize *= 512;
return OK;
}
6 changes: 6 additions & 0 deletions VolumeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,10 @@ class VolumeManager {
bool mSecureKeyguardShowing;
};

namespace android {
namespace vold {
android::status_t GetStorageSize(int64_t* storageSize);
}
} // namespace android

#endif
2 changes: 2 additions & 0 deletions binder/android/os/IVold.aidl
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ interface IVold {

void destroyDsuMetadataKey(@utf8InCpp String dsuSlot);

long getStorageSize();

const int FSTRIM_FLAG_DEEP_TRIM = 1;

const int MOUNT_FLAG_PRIMARY = 1;
Expand Down
4 changes: 4 additions & 0 deletions vdc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ int main(int argc, char** argv) {
checkStatus(args, vold->shutdown());
} else if (args[0] == "volume" && args[1] == "reset") {
checkStatus(args, vold->reset());
} else if (args[0] == "volume" && args[1] == "getStorageSize") {
int64_t size;
checkStatus(args, vold->getStorageSize(&size));
LOG(INFO) << size;
} else if (args[0] == "cryptfs" && args[1] == "bindkeys") {
bindkeys(args, vold);
} else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 5) {
Expand Down

0 comments on commit 29ab036

Please sign in to comment.