vold: skip first disk change when converting MBR to GPT

When converting a public (MBR) partition to private (GPT) partition,
'sgdisk --zap-all <path>' triggers a disk change netlink event
when converting from MBR to GPT.  Then, 'sgdisk --new=....' triggers
another disk change netlink event.

vold informs clients a new volume is created after the first disk
change event occurs.  system server reacts by requesting to mount
the volume.  If this request is honored before the second disk change
event, the volume will be unmounted immediately after system server's
request to mount is honored.  The next time system server performs
an operation (createnewuser) on this volume, it will fail due to
the volume being unmounted.

This is reproduced by running the following commands in a loop:

adb shell sm partition <disk> private
adb shell sm partition <disk> public
adb shell sm forget all

OR

run cts -c com.android.cts.appsecurity.AdoptableHostTest -m testPackageInstaller

This change causes vold to delay notifying clients that the volume is
ready until after it's actually partitioned.

CYNGNOS-2283
Change-Id: I457cc1508573d73ef2be2f0cfdc5c2237bfabad7
gugelfrei
Scott Mertz 8 years ago committed by Michael Bestas
parent bc2566c837
commit c731e3d038

@ -97,7 +97,8 @@ Disk::Disk(const std::string& eventPath, dev_t device, const std::string& nickna
mNickname(nickname),
mFlags(flags),
mCreated(false),
mJustPartitioned(false) {
mJustPartitioned(false),
mSkipChange(false) {
mId = StringPrintf("disk:%u,%u", major(device), minor(device));
mEventPath = eventPath;
mSysPath = StringPrintf("/sys/%s", eventPath.c_str());
@ -235,6 +236,11 @@ void Disk::destroyAllVolumes() {
}
status_t Disk::readMetadata() {
if (mSkipChange) {
return OK;
}
mSize = -1;
mLabel.clear();
@ -326,6 +332,12 @@ status_t Disk::readPartitions() {
return -ENOTSUP;
}
if (mSkipChange) {
mSkipChange = false;
LOG(INFO) << "Skip first change";
return OK;
}
destroyAllVolumes();
// Parse partition table
@ -446,9 +458,46 @@ status_t Disk::partitionPublic() {
destroyAllVolumes();
mJustPartitioned = true;
// First nuke any existing partition table
// Determine if we're coming from MBR
std::vector<std::string> cmd;
cmd.push_back(kSgdiskPath);
cmd.push_back("--android-dump");
cmd.push_back(mDevPath);
std::vector<std::string> output;
res = ForkExecvp(cmd, &output);
if (res != OK) {
LOG(WARNING) << "sgdisk failed to scan " << mDevPath;
mJustPartitioned = false;
return res;
}
Table table = Table::kUnknown;
for (auto line : output) {
char* cline = (char*) line.c_str();
char* token = strtok(cline, kSgdiskToken);
if (token == nullptr) continue;
if (!strcmp(token, "DISK")) {
const char* type = strtok(nullptr, kSgdiskToken);
if (!strcmp(type, "mbr")) {
table = Table::kMbr;
break;
} else if (!strcmp(type, "gpt")) {
table = Table::kGpt;
break;
}
}
}
if (table == Table::kMbr) {
LOG(INFO) << "skip first disk change event due to MBR -> GPT switch";
mSkipChange = true;
}
// First nuke any existing partition table
cmd.clear();
cmd.push_back(kSgdiskPath);
cmd.push_back("--zap-all");
cmd.push_back(mDevPath);

@ -111,6 +111,8 @@ class Disk {
bool mCreated;
/* Flag that we just partitioned and should format all volumes */
bool mJustPartitioned;
/* Flag that we need to skip first disk change events after partitioning*/
bool mSkipChange;
void createPublicVolume(dev_t device);
void createPrivateVolume(dev_t device, const std::string& partGuid);

Loading…
Cancel
Save