Recover from FUSE session starting failures
Vold calls into StorageManagerService which in turn calls into the FUSE daemon to start the session. If the system_server is very busy e.g right after an OTA, the session may not start quickly enough and we will timeout, causing vold to fail the mount. Previously, the only solution would be for the user to reboot. Now, we naively retry every 10s. Bug: 147610762 Test: Causing an artificial timeout when starting a session for the firs time, verified we recover after a minute Change-Id: Ifdb2384696e85b6774a12394798fca8eb75a584e
This commit is contained in:
@@ -44,6 +44,7 @@ import static com.android.internal.util.XmlUtils.readStringAttribute;
|
||||
import static com.android.internal.util.XmlUtils.writeIntAttribute;
|
||||
import static com.android.internal.util.XmlUtils.writeLongAttribute;
|
||||
import static com.android.internal.util.XmlUtils.writeStringAttribute;
|
||||
import static com.android.server.storage.StorageUserConnection.REMOTE_TIMEOUT_SECONDS;
|
||||
|
||||
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
|
||||
import static org.xmlpull.v1.XmlPullParser.START_TAG;
|
||||
@@ -1985,16 +1986,28 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
Slog.i(TAG, "Mounting volume " + vol);
|
||||
mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
|
||||
@Override
|
||||
public boolean onVolumeChecking(FileDescriptor deviceFd, String path,
|
||||
public boolean onVolumeChecking(FileDescriptor fd, String path,
|
||||
String internalPath) {
|
||||
vol.path = path;
|
||||
vol.internalPath = internalPath;
|
||||
ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd);
|
||||
try {
|
||||
mStorageSessionController.onVolumeMount(deviceFd, vol);
|
||||
mStorageSessionController.onVolumeMount(pfd, vol);
|
||||
return true;
|
||||
} catch (ExternalStorageServiceException e) {
|
||||
Slog.i(TAG, "Failed to mount volume " + vol, e);
|
||||
Slog.e(TAG, "Failed to mount volume " + vol, e);
|
||||
|
||||
Slog.i(TAG, "Scheduling reset in one minute");
|
||||
mHandler.removeMessages(H_RESET);
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(H_RESET),
|
||||
TimeUnit.SECONDS.toMillis(REMOTE_TIMEOUT_SECONDS * 2));
|
||||
return false;
|
||||
} finally {
|
||||
try {
|
||||
pfd.close();
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Failed to close FUSE device fd", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -40,9 +40,7 @@ import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -82,7 +80,7 @@ public final class StorageSessionController {
|
||||
* @throws ExternalStorageServiceException if the session fails to start
|
||||
* @throws IllegalStateException if a session has already been created for {@code vol}
|
||||
*/
|
||||
public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol)
|
||||
public void onVolumeMount(ParcelFileDescriptor deviceFd, VolumeInfo vol)
|
||||
throws ExternalStorageServiceException {
|
||||
if (!shouldHandle(vol)) {
|
||||
return;
|
||||
@@ -102,8 +100,8 @@ public final class StorageSessionController {
|
||||
mConnections.put(userId, connection);
|
||||
}
|
||||
Slog.i(TAG, "Creating and starting session with id: " + sessionId);
|
||||
connection.startSession(sessionId, new ParcelFileDescriptor(deviceFd),
|
||||
vol.getPath().getPath(), vol.getInternalPath().getPath());
|
||||
connection.startSession(sessionId, deviceFd, vol.getPath().getPath(),
|
||||
vol.getInternalPath().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +183,7 @@ public final class StorageSessionController {
|
||||
* This call removes all sessions for the user that is being stopped;
|
||||
* this will make sure that we don't rebind to the service needlessly.
|
||||
*/
|
||||
public void onUserStopping(int userId) throws ExternalStorageServiceException {
|
||||
public void onUserStopping(int userId) {
|
||||
if (!shouldHandle(null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,8 @@ import java.util.concurrent.TimeoutException;
|
||||
*/
|
||||
public final class StorageUserConnection {
|
||||
private static final String TAG = "StorageUserConnection";
|
||||
private static final int REMOTE_TIMEOUT_SECONDS = 15;
|
||||
|
||||
public static final int REMOTE_TIMEOUT_SECONDS = 5;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private final Context mContext;
|
||||
|
||||
Reference in New Issue
Block a user