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 
16 #pragma once
17 
18 #include <stdint.h>
19 #include <sys/types.h>
20 
21 #include <condition_variable>
22 #include <mutex>
23 #include <string>
24 
25 #include <snapuserd/snapuserd_kernel.h>
26 #include <storage_literals/storage_literals.h>
27 
28 namespace android {
29 namespace snapshot {
30 
31 using namespace android::storage_literals;
32 
33 class UpdateVerify {
34   public:
35     UpdateVerify(const std::string& misc_name);
36     void VerifyUpdatePartition();
37     bool CheckPartitionVerification();
38 
39   private:
40     enum class UpdateVerifyState {
41         VERIFY_UNKNOWN,
42         VERIFY_FAILED,
43         VERIFY_SUCCESS,
44     };
45 
46     std::string misc_name_;
47     UpdateVerifyState state_;
48     std::mutex m_lock_;
49     std::condition_variable m_cv_;
50 
51     /*
52      * Scanning of partitions is an expensive operation both in terms of memory
53      * and CPU usage. The goal here is to scan the partitions fast enough without
54      * significant increase in the boot time.
55      *
56      * Partitions such as system, product which may be huge and may need multiple
57      * threads to speed up the verification process. Using multiple threads for
58      * all partitions may increase CPU usage significantly. Hence, limit that to
59      * 1 thread per partition.
60      *
61      * These numbers were derived by monitoring the memory and CPU pressure
62      * (/proc/pressure/{cpu,memory}; and monitoring the Inactive(file) and
63      * Active(file) pages from /proc/meminfo.
64      *
65      * Additionally, for low memory devices, it is advisible to use O_DIRECT
66      * fucntionality for source block device.
67      */
68     int kMinThreadsToVerify = 1;
69     int kMaxThreadsToVerify = 3;
70     uint64_t kThresholdSize = 750_MiB;
71     uint64_t kBlockSizeVerify = 2_MiB;
72 
IsBlockAligned(uint64_t read_size)73     bool IsBlockAligned(uint64_t read_size) { return ((read_size & (BLOCK_SZ - 1)) == 0); }
74     void UpdatePartitionVerificationState(UpdateVerifyState state);
75     bool VerifyPartition(const std::string& partition_name, const std::string& dm_block_device);
76     bool VerifyBlocks(const std::string& partition_name, const std::string& dm_block_device,
77                       off_t offset, int skip_blocks, uint64_t dev_sz);
78 };
79 
80 }  // namespace snapshot
81 }  // namespace android
82