int Volume::unmountVol(bool force, bool revert) { int i, rc; if (getState() != Volume::State_Mounted) { SLOGE("Volume %s unmount request when not mounted", getLabel()); errno = EINVAL; return UNMOUNT_NOT_MOUNTED_ERR; } setState(Volume::State_Unmounting); usleep(1000 * 1000); // Give the framework some time to react /* * First move the mountpoint back to our internal staging point * so nobody else can muck with it while we work. */ if (doMoveMount(getMountpoint(), SEC_STGDIR, force)) { SLOGE("Failed to move mount %s => %s (%s)", getMountpoint(), SEC_STGDIR, strerror(errno)); setState(Volume::State_Mounted); return -1; } protectFromAutorunStupidity(); /* * Unmount the tmpfs which was obscuring the asec image directory * from non root users */ if (doUnmount(Volume::SEC_STG_SECIMGDIR, force)) { SLOGE("Failed to unmount tmpfs on %s (%s)", SEC_STG_SECIMGDIR, strerror(errno)); goto fail_republish; } /* * Remove the bindmount we were using to keep a reference to * the previously obscured directory. */ if (doUnmount(Volume::SEC_ASECDIR, force)) { SLOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR, strerror(errno)); goto fail_remount_tmpfs; } /* * Finally, unmount the actual block device from the staging dir */ if (doUnmount(Volume::SEC_STGDIR, force)) { SLOGE("Failed to unmount %s (%s)", SEC_STGDIR, strerror(errno)); goto fail_recreate_bindmount; } SLOGI("%s unmounted sucessfully", getMountpoint()); /* If this is an encrypted volume, and we've been asked to undo * the crypto mapping, then revert the dm-crypt mapping, and revert * the device info to the original values. */ if (revert && isDecrypted()) { cryptfs_revert_volume(getLabel()); revertDeviceInfo(); SLOGI("Encrypted volume %s reverted successfully", getMountpoint()); } setState(Volume::State_Idle); mCurrentlyMountedKdev = -1; return 0; /* * Failure handling - try to restore everything back the way it was */ fail_recreate_bindmount: if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR, "", MS_BIND, NULL)) { SLOGE("Failed to restore bindmount after failure! - Storage will appear offline!"); goto out_nomedia; } fail_remount_tmpfs: if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=0,uid=0,gid=0")) { SLOGE("Failed to restore tmpfs after failure! - Storage will appear offline!"); goto out_nomedia; } fail_republish: if (doMoveMount(SEC_STGDIR, getMountpoint(), force)) { SLOGE("Failed to republish mount after failure! - Storage will appear offline!"); goto out_nomedia; } setState(Volume::State_Mounted); return -1; out_nomedia: setState(Volume::State_NoMedia); return -1; }
int Volume::unmountVol(bool force, bool revert) { int i, rc; int flags = getFlags(); bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0; bool is_emulated_sd = false; #ifdef MTK_SHARED_SDCARD if (IsEmmcStorage()) { providesAsec = false; is_emulated_sd = true; } #endif if (getState() != Volume::State_Mounted) { SLOGE("Volume %s unmount request when not mounted", getLabel()); errno = EINVAL; return UNMOUNT_NOT_MOUNTED_ERR; } #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (false == isMountpointMounted(getFuseMountpoint())) { SLOGD("usbotg: Volume unmountVol %s is already unmounted", getFuseMountpoint()); goto unmount_success; } #endif setState(Volume::State_Unmounting); usleep(1000 * 100); // Give the framework some time to react char service[64]; char service_id[64]; strcpy(service_id, getMountpoint()+strlen(Volume::MEDIA_DIR)+1); snprintf(service, 64, "fuse_%s", service_id); if (is_emulated_sd) { snprintf(service, 64, "sdcard"); } #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (0 == strcmp(getLabel(), "usbotg")) { sPid = mPid; SLOGD("usbotg: Volume unmountVol ,mPid=%d",mPid); if(-1 != mPid) { kill(mPid,SIGKILL); } SLOGD("usbotg: Volume unmountVol ,mountpoint=%s",getFuseMountpoint()); if (doUnmount(getFuseMountpoint(), force)) { SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno)); goto fail_remount_secure; } if (doUnmount(getMountpoint(), force)) { SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno)); goto fail_remount_secure; } SLOGI("usbotg: Volume unmounted sucessfully"); } else { property_set("ctl.stop", service); /* Give it a chance to stop. I wish we had a synchronous way to determine this... */ //sleep(1); waitForServiceState(service, "stopped"); // TODO: determine failure mode if FUSE times out if (providesAsec && doUnmount(Volume::SEC_ASECDIR_EXT, force) != 0) { SLOGE("Failed to unmount secure area on %s (%s)", getMountpoint(), strerror(errno)); goto out_mounted; } /* Now that the fuse daemon is dead, unmount it */ if (doUnmount(getFuseMountpoint(), force) != 0) { SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno)); goto fail_remount_secure; } /* Unmount the real sd card */ if (!is_emulated_sd) { if (doUnmount(getMountpoint(), force) != 0) { SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno)); goto fail_remount_secure; } SLOGI("%s unmounted successfully", getMountpoint()); } } #else { #define MAX_NEED_TO_WAIT 10 bool need_to_wait = false; int need_to_wait_count = 0; do { Process::killProcessesWithOpenFiles(getFuseMountpoint(), 0, "mdlogger", &need_to_wait); if(need_to_wait) { need_to_wait_count++; SLOGI("need_to_wait=%d, need_to_wait_count=%d,", need_to_wait, need_to_wait_count); usleep(1000*1000); } else { break; } } while (need_to_wait && need_to_wait_count < MAX_NEED_TO_WAIT); property_set("ctl.stop", service); /* Give it a chance to stop. I wish we had a synchronous way to determine this... */ //sleep(1); waitForServiceState(service, "stopped"); // TODO: determine failure mode if FUSE times out if (providesAsec && doUnmount(Volume::SEC_ASECDIR_EXT, force) != 0) { SLOGE("Failed to unmount secure area on %s (%s)", getMountpoint(), strerror(errno)); goto out_mounted; } /* Now that the fuse daemon is dead, unmount it */ if (doUnmount(getFuseMountpoint(), force) != 0) { SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno)); goto fail_remount_secure; } /* Unmount the real sd card */ if (!is_emulated_sd) { if (doUnmount(getMountpoint(), force) != 0) { SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno)); goto fail_remount_secure; } SLOGI("%s unmounted successfully", getMountpoint()); } } #endif /* If this is an encrypted volume, and we've been asked to undo * the crypto mapping, then revert the dm-crypt mapping, and revert * the device info to the original values. */ if (revert && isDecrypted()) { cryptfs_revert_volume(getLabel()); revertDeviceInfo(); SLOGI("Encrypted volume %s reverted successfully", getMountpoint()); } setUuid(NULL); setUserLabel(NULL); setState(Volume::State_Idle); unmount_success: mCurrentlyMountedKdev = -1; #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (0 == strcmp(getLabel(), "usbotg")) { char cmd[255] = {0}; sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); //remove(getMountpoint()); } #endif return 0; fail_remount_secure: if (providesAsec && mountAsecExternal() != 0) { SLOGE("Failed to remount secure area (%s)", strerror(errno)); goto out_nomedia; } out_mounted: property_set("ctl.start", service); waitForServiceState(service, "running"); setState(Volume::State_Mounted); return -1; out_nomedia: setState(Volume::State_NoMedia); return -1; }