DO NOT MERGE Fix deadlock in MountService

It is not safe to call into vold with a lock held on mVolumeStates
since we will receive events back from vold on a different thread.
So in the boot completed handler we make a copy of the volume list and
then call vold to mount volumes after releasing the lock

Change-Id: Iaadfb1b8be5567c8e228a8fbc69d4d483c8dc987
Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2011-04-05 10:05:47 -04:00
parent e3b498be0a
commit 0aa5d7b7f2

View File

@ -444,31 +444,46 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
* to make the media scanner run. * to make the media scanner run.
*/ */
if ("simulator".equals(SystemProperties.get("ro.product.device"))) { if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
notifyVolumeStateChange(null, "/sdcard", VolumeState.NoMedia, VolumeState.Mounted); notifyVolumeStateChange(null, "/sdcard", VolumeState.NoMedia,
VolumeState.Mounted);
return; return;
} }
new Thread() { new Thread() {
@Override @Override
public void run() { public void run() {
try { try {
// it is not safe to call vold with mVolumeStates locked
// so we make a copy of the paths and states and process them
// outside the lock
String[] paths, states;
int count;
synchronized (mVolumeStates) { synchronized (mVolumeStates) {
for (String path : mVolumeStates.keySet()) { Set<String> keys = mVolumeStates.keySet();
String state = mVolumeStates.get(path); count = keys.size();
paths = (String[])keys.toArray(new String[count]);
states = new String[count];
for (int i = 0; i < count; i++) {
states[i] = mVolumeStates.get(paths[i]);
}
}
if (state.equals(Environment.MEDIA_UNMOUNTED)) { for (int i = 0; i < count; i++) {
int rc = doMountVolume(path); String path = paths[i];
if (rc != StorageResultCode.OperationSucceeded) { String state = states[i];
Slog.e(TAG, String.format("Boot-time mount failed (%d)",
rc)); if (state.equals(Environment.MEDIA_UNMOUNTED)) {
} int rc = doMountVolume(path);
} else if (state.equals(Environment.MEDIA_SHARED)) { if (rc != StorageResultCode.OperationSucceeded) {
/* Slog.e(TAG, String.format("Boot-time mount failed (%d)",
* Bootstrap UMS enabled state since vold indicates rc));
* the volume is shared (runtime restart while ums enabled)
*/
notifyVolumeStateChange(null, path, VolumeState.NoMedia,
VolumeState.Shared);
} }
} else if (state.equals(Environment.MEDIA_SHARED)) {
/*
* Bootstrap UMS enabled state since vold indicates
* the volume is shared (runtime restart while ums enabled)
*/
notifyVolumeStateChange(null, path, VolumeState.NoMedia,
VolumeState.Shared);
} }
} }