1 // Copyright (C) 2020 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <poll.h> 18 #include <sys/eventfd.h> 19 20 #include <cstdio> 21 #include <cstring> 22 #include <functional> 23 #include <future> 24 #include <iostream> 25 #include <mutex> 26 #include <optional> 27 #include <queue> 28 #include <sstream> 29 #include <string> 30 #include <thread> 31 #include <vector> 32 33 #include <android-base/unique_fd.h> 34 #include "snapuserd_core.h" 35 36 namespace android { 37 namespace snapshot { 38 39 static constexpr uint32_t kMaxPacketSize = 512; 40 static constexpr uint8_t kMaxMergeThreads = 2; 41 42 enum class DaemonOps { 43 INIT, 44 START, 45 QUERY, 46 STOP, 47 DELETE, 48 DETACH, 49 SUPPORTS, 50 INITIATE, 51 PERCENTAGE, 52 GETSTATUS, 53 UPDATE_VERIFY, 54 INVALID, 55 }; 56 57 class HandlerThread { 58 public: 59 explicit HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd); 60 FreeResources()61 void FreeResources() { 62 // Each worker thread holds a reference to snapuserd. 63 // Clear them so that all the resources 64 // held by snapuserd is released 65 if (snapuserd_) { 66 snapuserd_->FreeResources(); 67 snapuserd_ = nullptr; 68 } 69 } snapuserd()70 const std::shared_ptr<SnapshotHandler>& snapuserd() const { return snapuserd_; } thread()71 std::thread& thread() { return thread_; } 72 misc_name()73 const std::string& misc_name() const { return misc_name_; } ThreadTerminated()74 bool ThreadTerminated() { return thread_terminated_; } SetThreadTerminated()75 void SetThreadTerminated() { thread_terminated_ = true; } 76 77 private: 78 std::thread thread_; 79 std::shared_ptr<SnapshotHandler> snapuserd_; 80 std::string misc_name_; 81 bool thread_terminated_ = false; 82 }; 83 84 class UserSnapshotServer { 85 private: 86 android::base::unique_fd sockfd_; 87 bool terminating_; 88 volatile bool received_socket_signal_ = false; 89 std::vector<struct pollfd> watched_fds_; 90 bool is_socket_present_ = false; 91 int num_partitions_merge_complete_ = 0; 92 int active_merge_threads_ = 0; 93 bool stop_monitor_merge_thread_ = false; 94 bool is_server_running_ = false; 95 bool io_uring_enabled_ = false; 96 std::optional<bool> is_merge_monitor_started_; 97 98 android::base::unique_fd monitor_merge_event_fd_; 99 100 std::mutex lock_; 101 102 using HandlerList = std::vector<std::shared_ptr<HandlerThread>>; 103 HandlerList dm_users_; 104 std::queue<std::shared_ptr<HandlerThread>> merge_handlers_; 105 106 void AddWatchedFd(android::base::borrowed_fd fd, int events); 107 void AcceptClient(); 108 bool HandleClient(android::base::borrowed_fd fd, int revents); 109 bool Recv(android::base::borrowed_fd fd, std::string* data); 110 bool Sendmsg(android::base::borrowed_fd fd, const std::string& msg); 111 bool Receivemsg(android::base::borrowed_fd fd, const std::string& str); 112 113 void ShutdownThreads(); 114 bool RemoveAndJoinHandler(const std::string& control_device); 115 DaemonOps Resolveop(std::string& input); 116 std::string GetDaemonStatus(); 117 void Parsemsg(std::string const& msg, const char delim, std::vector<std::string>& out); 118 IsTerminating()119 bool IsTerminating() { return terminating_; } 120 121 void RunThread(std::shared_ptr<HandlerThread> handler); 122 void MonitorMerge(); 123 124 void JoinAllThreads(); 125 bool StartWithSocket(bool start_listening); 126 127 // Find a HandlerThread within a lock. 128 HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock, 129 const std::string& misc_name); 130 131 double GetMergePercentage(std::lock_guard<std::mutex>* proof_of_lock); 132 void TerminateMergeThreads(std::lock_guard<std::mutex>* proof_of_lock); 133 134 bool UpdateVerification(std::lock_guard<std::mutex>* proof_of_lock); 135 136 public: 137 UserSnapshotServer(); 138 ~UserSnapshotServer(); 139 140 bool Start(const std::string& socketname); 141 bool Run(); 142 void Interrupt(); 143 bool RunForSocketHandoff(); 144 bool WaitForSocket(); 145 146 std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name, 147 const std::string& cow_device_path, 148 const std::string& backing_device, 149 const std::string& base_path_merge); 150 bool StartHandler(const std::shared_ptr<HandlerThread>& handler); 151 bool StartMerge(std::lock_guard<std::mutex>* proof_of_lock, 152 const std::shared_ptr<HandlerThread>& handler); 153 std::string GetMergeStatus(const std::shared_ptr<HandlerThread>& handler); 154 155 void WakeupMonitorMergeThread(); SetTerminating()156 void SetTerminating() { terminating_ = true; } ReceivedSocketSignal()157 void ReceivedSocketSignal() { received_socket_signal_ = true; } SetServerRunning()158 void SetServerRunning() { is_server_running_ = true; } IsServerRunning()159 bool IsServerRunning() { return is_server_running_; } SetIouringEnabled()160 void SetIouringEnabled() { io_uring_enabled_ = true; } IsIouringEnabled()161 bool IsIouringEnabled() { return io_uring_enabled_; } 162 }; 163 164 } // namespace snapshot 165 } // namespace android 166