vold: Add 'force' option to anything that can cause an unmount

Signed-off-by: San Mehat <san@google.com>
This commit is contained in:
San Mehat 2010-02-18 09:00:18 -08:00
parent d31e380bd9
commit 4ba8948dc1
6 changed files with 53 additions and 38 deletions

View file

@ -59,7 +59,11 @@ int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
} else if (!strcmp(argv[1], "mount")) {
rc = vm->mountVolume(argv[2]);
} else if (!strcmp(argv[1], "unmount")) {
rc = vm->unmountVolume(argv[2]);
bool force = false;
if (argc >= 4 && !strcmp(argv[3], "force")) {
force = true;
}
rc = vm->unmountVolume(argv[2], force);
} else if (!strcmp(argv[1], "format")) {
rc = vm->formatVolume(argv[2]);
} else if (!strcmp(argv[1], "share")) {
@ -244,11 +248,15 @@ int CommandListener::AsecCmd::runCommand(SocketClient *cli,
cli->sendMsg(ResponseCode::CommandOkay, "Container finalized", false);
}
} else if (!strcmp(argv[1], "destroy")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy <container-id>", false);
if (argc < 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy <container-id> [force]", false);
return 0;
}
if (vm->destroyAsec(argv[2])) {
bool force = false;
if (argc > 3 && !strcmp(argv[3], "force")) {
force = true;
}
if (vm->destroyAsec(argv[2], force)) {
cli->sendMsg(ResponseCode::OperationFailed, "Container destroy failed", true);
} else {
cli->sendMsg(ResponseCode::CommandOkay, "Container destroyed", false);
@ -267,13 +275,16 @@ int CommandListener::AsecCmd::runCommand(SocketClient *cli,
} else {
cli->sendMsg(ResponseCode::CommandOkay, "Mount succeeded", false);
}
} else if (!strcmp(argv[1], "unmount")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount <container-id>", false);
if (argc < 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount <container-id> [force]", false);
return 0;
}
if (vm->unmountAsec(argv[2])) {
bool force = false;
if (argc > 3 && !strcmp(argv[3], "force")) {
force = true;
}
if (vm->unmountAsec(argv[2], force)) {
cli->sendMsg(ResponseCode::OperationFailed, "Container unmount failed", true);
} else {
cli->sendMsg(ResponseCode::CommandOkay, "Container unmounted", false);

View file

@ -274,7 +274,7 @@ void DirectVolume::handlePartitionRemoved(const char *devpath, NetlinkEvent *evt
getLabel(), getMountpoint(), major, minor);
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
msg, false);
if (Volume::unmountVol()) {
if (Volume::unmountVol(true)) {
LOGE("Failed to unmount volume on bad removal (%s)",
strerror(errno));
// XXX: At this point we're screwed for now

View file

@ -275,7 +275,7 @@ int Volume::mountVol() {
return -1;
}
int Volume::unmountVol() {
int Volume::unmountVol(bool force) {
int i, rc;
if (getState() != Volume::State_Mounted) {
@ -285,7 +285,7 @@ int Volume::unmountVol() {
}
setState(Volume::State_Unmounting);
usleep(1000 * 200); // Give the framework some time to react
usleep(1000 * 1000); // Give the framework some time to react
for (i = 1; i <= 10; i++) {
rc = umount(getMountpoint());
if (!rc)
@ -299,17 +299,18 @@ int Volume::unmountVol() {
LOGW("Volume %s unmount attempt %d failed (%s)",
getLabel(), i, strerror(errno));
int action;
int action = 0;
if (i > 8) {
action = 2; // SIGKILL
} else if (i > 7) {
action = 1; // SIGHUP
} else
action = 0; // just complain
if (force) {
if (i > 8) {
action = 2; // SIGKILL
} else if (i > 7) {
action = 1; // SIGHUP
}
}
Process::killProcessesWithOpenFiles(getMountpoint(), action);
usleep(1000*250);
usleep(1000*1000);
}
if (!rc) {
@ -319,6 +320,7 @@ int Volume::unmountVol() {
return 0;
}
errno = EBUSY;
LOGE("Volume %s failed to unmount (%s)\n", getLabel(), strerror(errno));
setState(Volume::State_Mounted);
return -1;

View file

@ -53,7 +53,7 @@ public:
virtual ~Volume();
int mountVol();
int unmountVol();
int unmountVol(bool force);
int formatVol();
const char *getLabel() { return mLabel; }

View file

@ -325,8 +325,8 @@ out_err:
return -1;
}
#define ASEC_UNMOUNT_RETRIES 10
int VolumeManager::unmountAsec(const char *id) {
#define ASEC_UNMOUNT_RETRIES 5
int VolumeManager::unmountAsec(const char *id, bool force) {
char asecFileName[255];
char mountPoint[255];
@ -353,20 +353,22 @@ int VolumeManager::unmountAsec(const char *id) {
LOGW("ASEC %s unmount attempt %d failed (%s)",
id, i, strerror(errno));
int action;
if (i > (ASEC_UNMOUNT_RETRIES - 2))
action = 2; // SIGKILL
else if (i > (ASEC_UNMOUNT_RETRIES - 3))
action = 1; // SIGHUP
else
action = 0; // Just complain
int action = 0; // default is to just complain
if (force) {
if (i > (ASEC_UNMOUNT_RETRIES - 2))
action = 2; // SIGKILL
else if (i > (ASEC_UNMOUNT_RETRIES - 3))
action = 1; // SIGHUP
}
Process::killProcessesWithOpenFiles(mountPoint, action);
usleep(1000 * 1000);
}
if (rc) {
LOGE("Failed to unmount ASEC %s", id);
errno = EBUSY;
LOGE("Failed to unmount container %s (%s)", id, strerror(errno));
return -1;
}
@ -397,7 +399,7 @@ int VolumeManager::unmountAsec(const char *id) {
return 0;
}
int VolumeManager::destroyAsec(const char *id) {
int VolumeManager::destroyAsec(const char *id, bool force) {
char asecFileName[255];
char mountPoint[255];
@ -407,7 +409,7 @@ int VolumeManager::destroyAsec(const char *id) {
if (isMountpointMounted(mountPoint)) {
LOGD("Unmounting container before destroy");
if (unmountAsec(id)) {
if (unmountAsec(id, force)) {
LOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
return -1;
}
@ -675,7 +677,7 @@ int VolumeManager::unshareVolume(const char *label, const char *method) {
return 0;
}
int VolumeManager::unmountVolume(const char *label) {
int VolumeManager::unmountVolume(const char *label, bool force) {
Volume *v = lookupVolume(label);
if (!v) {
@ -698,13 +700,13 @@ int VolumeManager::unmountVolume(const char *label) {
while(mActiveContainers->size()) {
AsecIdCollection::iterator it = mActiveContainers->begin();
LOGI("Unmounting ASEC %s (dependant on %s)", *it, v->getMountpoint());
if (unmountAsec(*it)) {
if (unmountAsec(*it, force)) {
LOGE("Failed to unmount ASEC %s (%s) - unmount of %s may fail!", *it,
strerror(errno), v->getMountpoint());
}
}
return v->unmountVol();
return v->unmountVol(force);
}
/*

View file

@ -52,7 +52,7 @@ public:
int listVolumes(SocketClient *cli);
int mountVolume(const char *label);
int unmountVolume(const char *label);
int unmountVolume(const char *label, bool force);
int shareVolume(const char *label, const char *method);
int unshareVolume(const char *label, const char *method);
int shareAvailable(const char *method, bool *avail);
@ -62,9 +62,9 @@ public:
int createAsec(const char *id, unsigned numSectors, const char *fstype,
const char *key, int ownerUid);
int finalizeAsec(const char *id);
int destroyAsec(const char *id);
int destroyAsec(const char *id, bool force);
int mountAsec(const char *id, const char *key, int ownerUid);
int unmountAsec(const char *id);
int unmountAsec(const char *id, bool force);
int renameAsec(const char *id1, const char *id2);
int getAsecMountPath(const char *id, char *buffer, int maxlen);