1 // Copyright (C) 2023 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 <memory>
18 #include <queue>
19 #include <string>
20 #include <thread>
21 #include <vector>
22 
23 #include <android-base/unique_fd.h>
24 #include <snapuserd/block_server.h>
25 
26 namespace android {
27 namespace snapshot {
28 
29 class SnapshotHandler;
30 
31 class HandlerThread {
32   public:
33     explicit HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd);
34 
35     void FreeResources();
snapuserd()36     const std::shared_ptr<SnapshotHandler>& snapuserd() const { return snapuserd_; }
thread()37     std::thread& thread() { return thread_; }
38 
misc_name()39     const std::string& misc_name() const { return misc_name_; }
ThreadTerminated()40     bool ThreadTerminated() { return thread_terminated_; }
SetThreadTerminated()41     void SetThreadTerminated() { thread_terminated_ = true; }
42 
43   private:
44     std::thread thread_;
45     std::shared_ptr<SnapshotHandler> snapuserd_;
46     std::string misc_name_;
47     bool thread_terminated_ = false;
48 };
49 
50 class ISnapshotHandlerManager {
51   public:
~ISnapshotHandlerManager()52     virtual ~ISnapshotHandlerManager() {}
53 
54     // Add a new snapshot handler but do not start serving requests yet.
55     virtual std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
56                                                       const std::string& cow_device_path,
57                                                       const std::string& backing_device,
58                                                       const std::string& base_path_merge,
59                                                       std::shared_ptr<IBlockServerOpener> opener,
60                                                       int num_worker_threads, bool use_iouring,
61                                                       bool o_direct) = 0;
62 
63     // Start serving requests on a snapshot handler.
64     virtual bool StartHandler(const std::string& misc_name) = 0;
65 
66     // Stop serving requests on a snapshot handler and remove it.
67     virtual bool DeleteHandler(const std::string& misc_name) = 0;
68 
69     // Begin merging blocks on the given snapshot handler.
70     virtual bool InitiateMerge(const std::string& misc_name) = 0;
71 
72     // Return a string containing a status code indicating the merge status
73     // on the handler. Returns empty on error.
74     virtual std::string GetMergeStatus(const std::string& misc_name) = 0;
75 
76     // Wait until all handlers have terminated.
77     virtual void JoinAllThreads() = 0;
78 
79     // Stop any in-progress merge threads.
80     virtual void TerminateMergeThreads() = 0;
81 
82     // Returns the merge progress across all merging snapshot handlers.
83     virtual double GetMergePercentage() = 0;
84 
85     // Returns whether all snapshots have verified.
86     virtual bool GetVerificationStatus() = 0;
87 
88     // Disable partition verification
89     virtual void DisableVerification() = 0;
90 };
91 
92 class SnapshotHandlerManager final : public ISnapshotHandlerManager {
93   public:
94     SnapshotHandlerManager();
95     std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
96                                               const std::string& cow_device_path,
97                                               const std::string& backing_device,
98                                               const std::string& base_path_merge,
99                                               std::shared_ptr<IBlockServerOpener> opener,
100                                               int num_worker_threads, bool use_iouring,
101                                               bool o_direct) override;
102     bool StartHandler(const std::string& misc_name) override;
103     bool DeleteHandler(const std::string& misc_name) override;
104     bool InitiateMerge(const std::string& misc_name) override;
105     std::string GetMergeStatus(const std::string& misc_name) override;
106     void JoinAllThreads() override;
107     void TerminateMergeThreads() override;
108     double GetMergePercentage() override;
109     bool GetVerificationStatus() override;
DisableVerification()110     void DisableVerification() override { perform_verification_ = false; }
111 
112   private:
113     bool StartHandler(const std::shared_ptr<HandlerThread>& handler);
114     void RunThread(std::shared_ptr<HandlerThread> handler);
115     bool StartMerge(std::lock_guard<std::mutex>* proof_of_lock,
116                     const std::shared_ptr<HandlerThread>& handler);
117     void MonitorMerge();
118     void WakeupMonitorMergeThread();
119     bool RemoveAndJoinHandler(const std::string& misc_name);
120 
121     // Find a HandlerThread within a lock.
122     using HandlerList = std::vector<std::shared_ptr<HandlerThread>>;
123     HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
124                                       const std::string& misc_name);
125 
126     std::mutex lock_;
127     HandlerList dm_users_;
128 
129     bool stop_monitor_merge_thread_ = false;
130     int active_merge_threads_ = 0;
131     std::thread merge_monitor_;
132     int num_partitions_merge_complete_ = 0;
133     std::queue<std::shared_ptr<HandlerThread>> merge_handlers_;
134     android::base::unique_fd monitor_merge_event_fd_;
135     bool perform_verification_ = true;
136 };
137 
138 }  // namespace snapshot
139 }  // namespace android
140