Expand virtio_block check to other virtual devices am: ff1fc9bc41

Change-Id: I2eda581574e0adecf1617624a66af92b540c35c4
gugelfrei
Alistair Delva 4 years ago committed by Automerger Merge Worker
commit ac8027eed5

@ -77,6 +77,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";
static const char* kAndroidDir = "/Android/";
@ -1103,8 +1104,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,

@ -155,8 +155,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);

@ -83,6 +83,7 @@ using android::vold::DeleteDirContents;
using android::vold::DeleteDirContentsAndDir;
using android::vold::EnsureDirExists;
using android::vold::IsFilesystemSupported;
using android::vold::IsVirtioBlkDevice;
using android::vold::PrepareAndroidDirs;
using android::vold::PrepareAppDirFromRoot;
using android::vold::PrivateVolume;
@ -103,8 +104,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;
using ScanProcCallback = bool(*)(uid_t uid, pid_t pid, int nsFd, const char* name, void* params);
@ -231,12 +230,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;
@ -322,7 +293,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";
@ -627,7 +598,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…
Cancel
Save