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