Expand virtio_block check to other virtual devices
The Android Emulator isn't the only virtual device the virtio-block detection code is useful for, and those platforms might not set any discriminating properties to indicate that they are virtual. Rework the virtio-block major detection to use /proc/devices instead of hardcoding the assumption that any virtual platform can have virtio-block at any experimental major; the new code permits only the exact experimental major assigned to virtio-block. The new code runs everywhere, but it will only run once and could be expanded later to detect dynamic or experimental majors. Bug: 156286088 Change-Id: Ieae805d08fddd0124a397636f04d99194a9ef7e5 Merged-In: Ieae805d08fddd0124a397636f04d99194a9ef7e5
This commit is contained in:
parent
b6e2c14ed1
commit
d3c230b5c9
4 changed files with 42 additions and 42 deletions
36
Utils.cpp
36
Utils.cpp
|
@ -70,6 +70,7 @@ bool sSleepOnUnmount = true;
|
|||
static const char* kBlkidPath = "/system/bin/blkid";
|
||||
static const char* kKeyPath = "/data/misc/vold";
|
||||
|
||||
static const char* kProcDevices = "/proc/devices";
|
||||
static const char* kProcFilesystems = "/proc/filesystems";
|
||||
|
||||
// Lock used to protect process-level SELinux changes from racing with each
|
||||
|
@ -796,8 +797,39 @@ bool Readlinkat(int dirfd, const std::string& path, std::string* result) {
|
|||
}
|
||||
}
|
||||
|
||||
bool IsRunningInEmulator() {
|
||||
return android::base::GetBoolProperty("ro.kernel.qemu", false);
|
||||
static unsigned int GetMajorBlockVirtioBlk() {
|
||||
std::string devices;
|
||||
if (!ReadFileToString(kProcDevices, &devices)) {
|
||||
PLOG(ERROR) << "Unable to open /proc/devices";
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool blockSection = false;
|
||||
for (auto line : android::base::Split(devices, "\n")) {
|
||||
if (line == "Block devices:") {
|
||||
blockSection = true;
|
||||
} else if (line == "Character devices:") {
|
||||
blockSection = false;
|
||||
} else if (blockSection) {
|
||||
auto tokens = android::base::Split(line, " ");
|
||||
if (tokens.size() == 2 && tokens[1] == "virtblk") {
|
||||
return std::stoul(tokens[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IsVirtioBlkDevice(unsigned int major) {
|
||||
// Most virtualized platforms expose block devices with the virtio-blk
|
||||
// block device driver. Unfortunately, this driver does not use a fixed
|
||||
// major number, but relies on the kernel to assign one from a specific
|
||||
// range of block majors, which are allocated for "LOCAL/EXPERIMENAL USE"
|
||||
// per Documentation/devices.txt. This is true even for the latest Linux
|
||||
// kernel (4.4; see init() in drivers/block/virtio_blk.c).
|
||||
static unsigned int kMajorBlockVirtioBlk = GetMajorBlockVirtioBlk();
|
||||
return kMajorBlockVirtioBlk && major == kMajorBlockVirtioBlk;
|
||||
}
|
||||
|
||||
static status_t findMountPointsWithPrefix(const std::string& prefix,
|
||||
|
|
4
Utils.h
4
Utils.h
|
@ -133,8 +133,8 @@ status_t RestoreconRecursive(const std::string& path);
|
|||
// TODO: promote to android::base
|
||||
bool Readlinkat(int dirfd, const std::string& path, std::string* result);
|
||||
|
||||
/* Checks if Android is running in QEMU */
|
||||
bool IsRunningInEmulator();
|
||||
// Handles dynamic major assignment for virtio-block
|
||||
bool IsVirtioBlkDevice(unsigned int major);
|
||||
|
||||
status_t UnmountTreeWithPrefix(const std::string& prefix);
|
||||
status_t UnmountTree(const std::string& mountPoint);
|
||||
|
|
|
@ -78,6 +78,7 @@ using android::vold::BindMount;
|
|||
using android::vold::CreateDir;
|
||||
using android::vold::DeleteDirContents;
|
||||
using android::vold::DeleteDirContentsAndDir;
|
||||
using android::vold::IsVirtioBlkDevice;
|
||||
using android::vold::Symlink;
|
||||
using android::vold::Unlink;
|
||||
using android::vold::UnmountTree;
|
||||
|
@ -94,8 +95,6 @@ static const std::string kEmptyString("");
|
|||
static const unsigned int kSizeVirtualDisk = 536870912;
|
||||
|
||||
static const unsigned int kMajorBlockMmc = 179;
|
||||
static const unsigned int kMajorBlockExperimentalMin = 240;
|
||||
static const unsigned int kMajorBlockExperimentalMax = 254;
|
||||
|
||||
VolumeManager* VolumeManager::sInstance = NULL;
|
||||
|
||||
|
@ -214,12 +213,10 @@ void VolumeManager::handleBlockEvent(NetlinkEvent* evt) {
|
|||
for (const auto& source : mDiskSources) {
|
||||
if (source->matches(eventPath)) {
|
||||
// For now, assume that MMC and virtio-blk (the latter is
|
||||
// emulator-specific; see Disk.cpp for details) devices are SD,
|
||||
// and that everything else is USB
|
||||
// specific to virtual platforms; see Utils.cpp for details)
|
||||
// devices are SD, and that everything else is USB
|
||||
int flags = source->getFlags();
|
||||
if (major == kMajorBlockMmc || (android::vold::IsRunningInEmulator() &&
|
||||
major >= (int)kMajorBlockExperimentalMin &&
|
||||
major <= (int)kMajorBlockExperimentalMax)) {
|
||||
if (major == kMajorBlockMmc || IsVirtioBlkDevice(major)) {
|
||||
flags |= android::vold::Disk::Flags::kSd;
|
||||
} else {
|
||||
flags |= android::vold::Disk::Flags::kUsb;
|
||||
|
|
|
@ -73,8 +73,6 @@ static const unsigned int kMajorBlockScsiN = 133;
|
|||
static const unsigned int kMajorBlockScsiO = 134;
|
||||
static const unsigned int kMajorBlockScsiP = 135;
|
||||
static const unsigned int kMajorBlockMmc = 179;
|
||||
static const unsigned int kMajorBlockExperimentalMin = 240;
|
||||
static const unsigned int kMajorBlockExperimentalMax = 254;
|
||||
static const unsigned int kMajorBlockDynamicMin = 234;
|
||||
static const unsigned int kMajorBlockDynamicMax = 512;
|
||||
|
||||
|
@ -88,33 +86,6 @@ enum class Table {
|
|||
kGpt,
|
||||
};
|
||||
|
||||
static bool isVirtioBlkDevice(unsigned int major) {
|
||||
/*
|
||||
* The new emulator's "ranchu" virtual board no longer includes a goldfish
|
||||
* MMC-based SD card device; instead, it emulates SD cards with virtio-blk,
|
||||
* which has been supported by upstream kernel and QEMU for quite a while.
|
||||
* Unfortunately, the virtio-blk block device driver does not use a fixed
|
||||
* major number, but relies on the kernel to assign one from a specific
|
||||
* range of block majors, which are allocated for "LOCAL/EXPERIMENAL USE"
|
||||
* per Documentation/devices.txt. This is true even for the latest Linux
|
||||
* kernel (4.4; see init() in drivers/block/virtio_blk.c).
|
||||
*
|
||||
* This makes it difficult for vold to detect a virtio-blk based SD card.
|
||||
* The current solution checks two conditions (both must be met):
|
||||
*
|
||||
* a) If the running environment is the emulator;
|
||||
* b) If the major number is an experimental block device major number (for
|
||||
* x86/x86_64 3.10 ranchu kernels, virtio-blk always gets major number
|
||||
* 253, but it is safer to match the range than just one value).
|
||||
*
|
||||
* Other conditions could be used, too, e.g. the hardware name should be
|
||||
* "ranchu", the device's sysfs path should end with "/block/vd[d-z]", etc.
|
||||
* But just having a) and b) is enough for now.
|
||||
*/
|
||||
return IsRunningInEmulator() && major >= kMajorBlockExperimentalMin &&
|
||||
major <= kMajorBlockExperimentalMax;
|
||||
}
|
||||
|
||||
static bool isNvmeBlkDevice(unsigned int major, const std::string& sysPath) {
|
||||
return sysPath.find("nvme") != std::string::npos && major >= kMajorBlockDynamicMin &&
|
||||
major <= kMajorBlockDynamicMax;
|
||||
|
@ -298,7 +269,7 @@ status_t Disk::readMetadata() {
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
if (isVirtioBlkDevice(majorId)) {
|
||||
if (IsVirtioBlkDevice(majorId)) {
|
||||
LOG(DEBUG) << "Recognized experimental block major ID " << majorId
|
||||
<< " as virtio-blk (emulator's virtual SD card device)";
|
||||
mLabel = "Virtual";
|
||||
|
@ -597,7 +568,7 @@ int Disk::getMaxMinors() {
|
|||
return std::stoi(tmp);
|
||||
}
|
||||
default: {
|
||||
if (isVirtioBlkDevice(majorId)) {
|
||||
if (IsVirtioBlkDevice(majorId)) {
|
||||
// drivers/block/virtio_blk.c has "#define PART_BITS 4", so max is
|
||||
// 2^4 - 1 = 15
|
||||
return 15;
|
||||
|
|
Loading…
Reference in a new issue