diff options
author | San Mehat <san@google.com> | 2010-02-18 09:00:18 -0800 |
---|---|---|
committer | San Mehat <san@google.com> | 2010-02-18 11:48:49 -0800 |
commit | 4ba8948dc16463053e21cda5744f519a555080d0 (patch) | |
tree | b033c6371d77569f490bf0b4a2a7e64dbac58882 | |
parent | d31e380bd9689dd9629b510ffe324707e261b439 (diff) | |
download | system_vold-4ba8948dc16463053e21cda5744f519a555080d0.tar.gz system_vold-4ba8948dc16463053e21cda5744f519a555080d0.tar.bz2 system_vold-4ba8948dc16463053e21cda5744f519a555080d0.zip |
vold: Add 'force' option to anything that can cause an unmount
Signed-off-by: San Mehat <san@google.com>
-rw-r--r-- | CommandListener.cpp | 27 | ||||
-rw-r--r-- | DirectVolume.cpp | 2 | ||||
-rw-r--r-- | Volume.cpp | 22 | ||||
-rw-r--r-- | Volume.h | 2 | ||||
-rw-r--r-- | VolumeManager.cpp | 32 | ||||
-rw-r--r-- | VolumeManager.h | 6 |
6 files changed, 53 insertions, 38 deletions
diff --git a/CommandListener.cpp b/CommandListener.cpp index b25728f..c87198e 100644 --- a/CommandListener.cpp +++ b/CommandListener.cpp @@ -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); diff --git a/DirectVolume.cpp b/DirectVolume.cpp index 68a6fcd..dcb1a05 100644 --- a/DirectVolume.cpp +++ b/DirectVolume.cpp @@ -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 @@ -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; @@ -53,7 +53,7 @@ public: virtual ~Volume(); int mountVol(); - int unmountVol(); + int unmountVol(bool force); int formatVol(); const char *getLabel() { return mLabel; } diff --git a/VolumeManager.cpp b/VolumeManager.cpp index 251e11c..72ec3da 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -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); } /* diff --git a/VolumeManager.h b/VolumeManager.h index f989cdb..5ed6f21 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -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); |