Apply lazy-umount and kill processes to unmount user partition 88/183088/8
authorseolheui kim <s414.kim@samsung.com>
Mon, 2 Jul 2018 06:20:59 +0000 (15:20 +0900)
committerseolheui, kim <s414.kim@samsung.com>
Fri, 13 Jul 2018 11:49:29 +0000 (20:49 +0900)
Change-Id: If6164ea25259877a88604c935fb4488765584872
Signed-off-by: seolheui kim <s414.kim@samsung.com>
server/engine/encryption/dmcrypt-engine.cpp
server/internal-encryption.cpp

index 6c1121f..60c217a 100644 (file)
@@ -286,11 +286,7 @@ void DMCryptEngine::mount(const BinaryData &key, unsigned int options)
 
 void DMCryptEngine::umount()
 {
-       //TODO umount("/opt/usr/"apps") will be removed
-       if (::umount("/opt/usr/apps") && errno != EINVAL)
-               ERROR(SINK, runtime::GetSystemErrorMessage());
-
-       if (::umount(destination.c_str()) && errno != EINVAL)
+       if (::umount(destination.c_str()) && errno != EINVAL && errno != ENOENT)
                throw runtime::Exception(runtime::GetSystemErrorMessage());
 
        destroyCryptoBlkDev(DM_DEFAULT_LABEL_NAME);
index 3fc0cd7..bf7cc99 100644 (file)
@@ -52,6 +52,9 @@ namespace ode {
 namespace {
 
 const char *PRIVILEGE_PLATFORM = "http://tizen.org/privilege/internal/default/platform";
+const std::vector<std::string> blackListSystemdUnits = {
+       "samsung-log-mgr.service",
+};
 
 // watches systemd jobs
 class JobWatch {
@@ -210,7 +213,6 @@ void stopDependedSystemdUnits()
 {
        dbus::Connection& systemDBus = dbus::Connection::getSystem();
        std::set<std::string> unitsToStop;
-       pid_t p = -1;
 
        for (pid_t pid : runtime::FileUser::getList(INTERNAL_PATH, true)) {
                try {
@@ -223,10 +225,7 @@ void stopDependedSystemdUnits()
                                                                                .get("(o)", &unit);
 
                        auto unescapedName = getDecodedPath(unit, "/org/freedesktop/systemd1/unit/");
-                       if (unescapedName == "samsung-log-mgr.service")
-                               p = pid;
-                       else
-                               unitsToStop.insert(unescapedName);
+                       unitsToStop.insert(unescapedName);
                } catch (runtime::Exception &e) {
                        INFO(SINK, "Killing process: " + std::to_string(pid));
                        ::kill(pid, SIGKILL);
@@ -234,6 +233,9 @@ void stopDependedSystemdUnits()
        }
 
        JobWatch watch(systemDBus);
+       for (auto unit : blackListSystemdUnits) {
+               unitsToStop.erase(unitsToStop.find(unit));
+       }
 
        for (const std::string& unit : unitsToStop) {
                INFO(SINK, "Stopping unit: " + unit);
@@ -247,12 +249,6 @@ void stopDependedSystemdUnits()
                if (!watch.waitForJob(job))
                        throw runtime::Exception("Stopping unit: " + unit + " failed");
        }
-
-       if (::umount2("/sys/fs/cgroup", MNT_FORCE | MNT_DETACH) != 0)
-               INFO(SINK, "Failed to unmount cgroup");
-
-       if (p != -1)
-               ::kill(p, SIGKILL);
 }
 
 void showProgressUI(const std::string type)
@@ -301,27 +297,61 @@ void setOptions(unsigned int options)
        ::vconf_set_bool(VCONFKEY_ODE_FAST_ENCRYPTION, value);
 }
 
-void unmountInternalStorage(const std::string& source)
+void execAndWait(const std::string &path, std::vector<std::string> &args)
 {
-       while(true) {
-               auto mntPaths = findMountPointsByDevice(source);
-               if(mntPaths.empty())
-                       break;
+       runtime::Process proc(path, args);
+       int ret = proc.execute();
+       if (ret < 0)
+               ERROR(SINK, path + " failed for " + args.back());
+
+       ret = proc.waitForFinished();
+       if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
+               ERROR(SINK, path + " failed for " + args.back());
+}
 
-               bool unmounted = true;
-               for(const auto& path : mntPaths) {
-                       INFO(SINK, "Unmounting " + path);
-                       if (::umount(path.c_str()) == -1) {
-                               // If it's busy or was already unmounted ignore the error
-                               if (errno != EBUSY && errno != EINVAL) {
-                                       throw runtime::Exception("umount() error: " + runtime::GetSystemErrorMessage());
-                               }
-                               unmounted = false;
-                       }
+bool isPartitionTerminated(const std::string &partition)
+{
+       bool ret = true;
+       const std::string cmd("fuser -m " + partition + " | grep -o '[0-9]*'");
+       char *line = nullptr;
+       size_t len = 0;
+
+       FILE *fp = ::popen(cmd.c_str(), "r");
+       if (fp == nullptr) {
+               ERROR(SINK, "Failed to get processes on partition");
+               return false;
+       }
+
+       if (::getline(&line, &len, fp) != -1)
+               ret = false;
+
+       ::free(line);
+       ::pclose(fp);
+
+       return ret;
+}
+
+void unmountInternalStorage(const std::string& source)
+{
+       if (::umount2("/opt/usr", MNT_DETACH) == -1) {
+               if (errno != EBUSY && errno != EINVAL) {
+                       throw runtime::Exception("umount() error : " + runtime::GetSystemErrorMessage());
                }
-               if (!unmounted)
-                       stopDependedSystemdUnits();
        }
+
+       do {
+               ::sync();
+               static const char *fuserPath = "/usr/bin/fuser";
+               std::vector<std::string> args = {
+                       fuserPath, "-m", "-k", "-s", "-SIGTERM", source,
+               };
+               execAndWait(fuserPath, args);
+               ::usleep((useconds_t)((unsigned int)(500)*1000));
+
+               args[4] = "-SIGKILL";
+               execAndWait(fuserPath, args);
+               ::usleep((useconds_t)((unsigned int)(200)*1000));
+       } while (!isPartitionTerminated(source));
 }
 
 }
@@ -418,8 +448,10 @@ int InternalEncryptionServer::umount()
 
        INFO(SINK, "Closing all processes using internal storage.");
        try {
+               stopKnownSystemdUnits();
                stopDependedSystemdUnits();
                INFO(SINK, "Umounting internal storage.");
+               unmountInternalStorage("/dev/mapper/userdata");
                engine->umount();
        } catch (runtime::Exception &e) {
                ERROR(SINK, "Umount failed: " + std::string(e.what()));
@@ -515,14 +547,8 @@ int InternalEncryptionServer::decrypt(const std::string& password)
                                stopDependedSystemdUnits();
 
                                INFO(SINK, "Umounting internal storage.");
-                               while (1) {
-                                       try {
-                                               engine->umount();
-                                               break;
-                                       } catch (runtime::Exception& e) {
-                                               stopDependedSystemdUnits();
-                                       }
-                               }
+                               unmountInternalStorage("/dev/mapper/userdata");
+                               engine->umount();
                        }
 
                        INFO(SINK, "Decryption started.");