Merge "Load kernel modules from /lib/modules/`uname -r`_$(page_size) if present" into main
diff --git a/fs_mgr/libfs_avb/avb_ops.cpp b/fs_mgr/libfs_avb/avb_ops.cpp
index a119bfc..cc19776 100644
--- a/fs_mgr/libfs_avb/avb_ops.cpp
+++ b/fs_mgr/libfs_avb/avb_ops.cpp
@@ -108,8 +108,8 @@
 // Converts a partition name (with ab_suffix) to the corresponding mount point.
 // e.g., "system_a" => "/system",
 // e.g., "vendor_a" => "/vendor",
-static std::string DeriveMountPoint(const std::string& partition_name) {
-    const std::string ab_suffix = fs_mgr_get_slot_suffix();
+static std::string DeriveMountPoint(const std::string& partition_name,
+                                    const std::string& ab_suffix) {
     std::string mount_point(partition_name);
     auto found = partition_name.rfind(ab_suffix);
     if (found != std::string::npos) {
@@ -119,7 +119,7 @@
     return "/" + mount_point;
 }
 
-FsManagerAvbOps::FsManagerAvbOps() {
+FsManagerAvbOps::FsManagerAvbOps(const std::string& slot_suffix) {
     // We only need to provide the implementation of read_from_partition()
     // operation since that's all what is being used by the avb_slot_verify().
     // Other I/O operations are only required in bootloader but not in
@@ -135,6 +135,11 @@
 
     // Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps.
     avb_ops_.user_data = this;
+
+    slot_suffix_ = slot_suffix;
+    if (slot_suffix_.empty()) {
+        slot_suffix_ = fs_mgr_get_slot_suffix();
+    }
 }
 
 // Given a partition name (with ab_suffix), e.g., system_a, returns the corresponding
@@ -149,7 +154,7 @@
         return "";
     }
 
-    const auto mount_point = DeriveMountPoint(partition_name);
+    const auto mount_point = DeriveMountPoint(partition_name, slot_suffix_);
     if (mount_point.empty()) return "";
 
     auto fstab_entry = GetEntryForMountPoint(&fstab_, mount_point);
diff --git a/fs_mgr/libfs_avb/avb_ops.h b/fs_mgr/libfs_avb/avb_ops.h
index 12686a6..709091e 100644
--- a/fs_mgr/libfs_avb/avb_ops.h
+++ b/fs_mgr/libfs_avb/avb_ops.h
@@ -48,7 +48,7 @@
 //
 class FsManagerAvbOps {
   public:
-    FsManagerAvbOps();
+    explicit FsManagerAvbOps(const std::string& slot_suffix = {});
 
     static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) {
         return reinterpret_cast<FsManagerAvbOps*>(ops->user_data);
@@ -66,6 +66,7 @@
     std::string GetPartitionPath(const char* partition_name);
     AvbOps avb_ops_;
     Fstab fstab_;
+    std::string slot_suffix_;
 };
 
 }  // namespace fs_mgr
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
index a288876..fb22423 100644
--- a/fs_mgr/libfs_avb/fs_avb.cpp
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -182,6 +182,11 @@
 
 // class AvbHandle
 // ---------------
+AvbHandle::AvbHandle() : status_(AvbHandleStatus::kUninitialized) {
+    slot_suffix_ = fs_mgr_get_slot_suffix();
+    other_slot_suffix_ = fs_mgr_get_other_slot_suffix();
+}
+
 AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(
         const std::string& partition_name, const std::string& ab_suffix,
         const std::string& ab_other_suffix, const std::string& expected_public_key_path,
@@ -194,6 +199,9 @@
         return nullptr;
     }
 
+    avb_handle->slot_suffix_ = ab_suffix;
+    avb_handle->other_slot_suffix_ = ab_other_suffix;
+
     std::string expected_key_blob;
     if (!expected_public_key_path.empty()) {
         if (access(expected_public_key_path.c_str(), F_OK) != 0) {
@@ -373,9 +381,14 @@
     return avb_handle;
 }
 
-AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta() {
+AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const std::string& slot_suffix) {
     // Loads inline vbmeta images, starting from /vbmeta.
-    return LoadAndVerifyVbmeta("vbmeta", fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix(),
+    auto suffix = slot_suffix;
+    if (suffix.empty()) {
+        suffix = fs_mgr_get_slot_suffix();
+    }
+    auto other_suffix = android::fs_mgr::OtherSlotSuffix(suffix);
+    return LoadAndVerifyVbmeta("vbmeta", suffix, other_suffix,
                                {} /* expected_public_key, already checked by bootloader */,
                                HashAlgorithm::kSHA256,
                                IsAvbPermissive(), /* allow_verification_error */
@@ -399,7 +412,7 @@
                                        ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
                                        : AVB_SLOT_VERIFY_FLAGS_NONE;
     AvbSlotVerifyResult verify_result =
-            avb_ops.AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->vbmeta_images_);
+            avb_ops.AvbSlotVerify(avb_handle->slot_suffix_, flags, &avb_handle->vbmeta_images_);
 
     // Only allow the following verify results:
     //   - AVB_SLOT_VERIFY_RESULT_OK.
@@ -492,7 +505,7 @@
     }
 
     if (!LoadAvbHashtreeToEnableVerity(fstab_entry, wait_for_verity_dev, vbmeta_images_,
-                                       fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
+                                       slot_suffix_, other_slot_suffix_)) {
         return AvbHashtreeResult::kFail;
     }
 
@@ -526,8 +539,8 @@
     if (vbmeta_images_.size() < 1) {
         return "";
     }
-    std::string avb_partition_name = DeriveAvbPartitionName(fstab_entry, fs_mgr_get_slot_suffix(),
-                                                            fs_mgr_get_other_slot_suffix());
+    std::string avb_partition_name =
+            DeriveAvbPartitionName(fstab_entry, slot_suffix_, other_slot_suffix_);
     auto avb_prop_name = "com.android.build." + avb_partition_name + ".security_patch";
     return GetAvbPropertyDescriptor(avb_prop_name, vbmeta_images_);
 }
diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
index 4702e68..924ab24 100644
--- a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
+++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
@@ -83,8 +83,8 @@
     //     is verified and can be trusted.
     //
     // TODO(bowgotsai): remove Open() and switch to LoadAndVerifyVbmeta().
-    static AvbUniquePtr Open();                 // loads inline vbmeta, via libavb.
-    static AvbUniquePtr LoadAndVerifyVbmeta();  // loads inline vbmeta.
+    static AvbUniquePtr Open();  // loads inline vbmeta, via libavb.
+    static AvbUniquePtr LoadAndVerifyVbmeta(const std::string& slot_suffix = {});
 
     // The caller can specify optional preload_avb_key_blobs for public key matching.
     // This is mostly for init to preload AVB keys before chroot into /system.
@@ -137,12 +137,14 @@
     AvbHandle& operator=(AvbHandle&&) noexcept = delete;  // no move assignment
 
   private:
-    AvbHandle() : status_(AvbHandleStatus::kUninitialized) {}
+    AvbHandle();
 
     std::vector<VBMetaData> vbmeta_images_;
     VBMetaInfo vbmeta_info_;  // A summary info for vbmeta_images_.
     AvbHandleStatus status_;
     std::string avb_version_;
+    std::string slot_suffix_;
+    std::string other_slot_suffix_;
 };
 
 }  // namespace fs_mgr
diff --git a/fs_mgr/libfstab/include/fstab/fstab.h b/fs_mgr/libfstab/include/fstab/fstab.h
index 150a47d..09471f0 100644
--- a/fs_mgr/libfstab/include/fstab/fstab.h
+++ b/fs_mgr/libfstab/include/fstab/fstab.h
@@ -145,5 +145,8 @@
 // Otherwise returns false and |*out| is not modified.
 bool GetKernelCmdline(const std::string& key, std::string* out);
 
+// Return the "other" slot for the given slot suffix.
+std::string OtherSlotSuffix(const std::string& suffix);
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/libfstab/slotselect.cpp b/fs_mgr/libfstab/slotselect.cpp
index 97b2ba1..db3f8da 100644
--- a/fs_mgr/libfstab/slotselect.cpp
+++ b/fs_mgr/libfstab/slotselect.cpp
@@ -74,3 +74,13 @@
     }
     return true;
 }
+
+namespace android {
+namespace fs_mgr {
+
+std::string OtherSlotSuffix(const std::string& suffix) {
+    return other_suffix(suffix);
+}
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
index 8add041..97974c4 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
@@ -32,9 +32,9 @@
     static std::unique_ptr<ICompressor> Gz(uint32_t compression_level);
     static std::unique_ptr<ICompressor> Brotli(uint32_t compression_level);
     static std::unique_ptr<ICompressor> Lz4(uint32_t compression_level);
-    static std::unique_ptr<ICompressor> Zstd(uint32_t compression_level);
+    static std::unique_ptr<ICompressor> Zstd(uint32_t compression_level, const int32_t BLOCK_SZ);
 
-    static std::unique_ptr<ICompressor> Create(CowCompression compression);
+    static std::unique_ptr<ICompressor> Create(CowCompression compression, const int32_t BLOCK_SZ);
 
     uint32_t GetCompressionLevel() const { return compression_level_; }
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
index 466b93c..71ac59f 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
@@ -55,7 +55,8 @@
     }
 }
 
-std::unique_ptr<ICompressor> ICompressor::Create(CowCompression compression) {
+std::unique_ptr<ICompressor> ICompressor::Create(CowCompression compression,
+                                                 const int32_t BLOCK_SZ) {
     switch (compression.algorithm) {
         case kCowCompressLz4:
             return ICompressor::Lz4(compression.compression_level);
@@ -64,7 +65,7 @@
         case kCowCompressGz:
             return ICompressor::Gz(compression.compression_level);
         case kCowCompressZstd:
-            return ICompressor::Zstd(compression.compression_level);
+            return ICompressor::Zstd(compression.compression_level, BLOCK_SZ);
         case kCowCompressNone:
             return nullptr;
     }
@@ -175,12 +176,10 @@
 
 class ZstdCompressor final : public ICompressor {
   public:
-    ZstdCompressor(uint32_t compression_level)
+    ZstdCompressor(uint32_t compression_level, const uint32_t MAX_BLOCK_SIZE)
         : ICompressor(compression_level), zstd_context_(ZSTD_createCCtx(), ZSTD_freeCCtx) {
         ZSTD_CCtx_setParameter(zstd_context_.get(), ZSTD_c_compressionLevel, compression_level);
-        // FIXME: hardcoding a value of 12 here for 4k blocks, should change to be either set by
-        // user, or optimized depending on block size
-        ZSTD_CCtx_setParameter(zstd_context_.get(), ZSTD_c_windowLog, 12);
+        ZSTD_CCtx_setParameter(zstd_context_.get(), ZSTD_c_windowLog, log2(MAX_BLOCK_SIZE));
     };
 
     std::basic_string<uint8_t> Compress(const void* data, size_t length) const override {
@@ -326,8 +325,8 @@
     return std::make_unique<Lz4Compressor>(compression_level);
 }
 
-std::unique_ptr<ICompressor> ICompressor::Zstd(uint32_t compression_level) {
-    return std::make_unique<ZstdCompressor>(compression_level);
+std::unique_ptr<ICompressor> ICompressor::Zstd(uint32_t compression_level, const int32_t BLOCK_SZ) {
+    return std::make_unique<ZstdCompressor>(compression_level, BLOCK_SZ);
 }
 
 void CompressWorker::Finalize() {
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
index 3692c1a..2aaf388 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
@@ -351,7 +351,7 @@
             return decompressed_size;
         }
         std::vector<unsigned char> ignore_buf(decompressed_size);
-        if (!Decompress(buffer, decompressed_size)) {
+        if (!Decompress(ignore_buf.data(), decompressed_size)) {
             return -1;
         }
         memcpy(buffer, ignore_buf.data() + ignore_bytes, buffer_size);
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
index f37aed1..1b5d724 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
@@ -17,9 +17,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <limits>
 #include <optional>
-#include <set>
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
@@ -103,7 +101,7 @@
     footer_ = parser.footer();
     fd_size_ = parser.fd_size();
     last_label_ = parser.last_label();
-    ops_ = std::move(parser.ops());
+    ops_ = parser.ops();
     data_loc_ = parser.data_loc();
 
     // If we're resuming a write, we're not ready to merge
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
index 0ecad9d..e59bd92 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
@@ -480,7 +480,7 @@
     std::string expected = "The quick brown fox jumps over the lazy dog.";
     expected.resize(4096, '\0');
 
-    std::unique_ptr<ICompressor> compressor = ICompressor::Create(compression);
+    std::unique_ptr<ICompressor> compressor = ICompressor::Create(compression, 4096);
     auto result = compressor->Compress(expected.data(), expected.size());
     ASSERT_FALSE(result.empty());
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
index 6757fa8..d3c3d59 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
@@ -183,7 +183,8 @@
         return;
     }
     for (int i = 0; i < num_compress_threads_; i++) {
-        std::unique_ptr<ICompressor> compressor = ICompressor::Create(compression_);
+        std::unique_ptr<ICompressor> compressor =
+                ICompressor::Create(compression_, header_.block_size);
         auto wt = std::make_unique<CompressWorker>(std::move(compressor), header_.block_size);
         threads_.emplace_back(std::async(std::launch::async, &CompressWorker::RunThread, wt.get()));
         compress_threads_.push_back(std::move(wt));
@@ -340,7 +341,7 @@
     compressed_buf_.clear();
     if (num_threads <= 1) {
         if (!compressor_) {
-            compressor_ = ICompressor::Create(compression_);
+            compressor_ = ICompressor::Create(compression_, header_.block_size);
         }
         return CompressWorker::CompressBlocks(compressor_.get(), options_.block_size, data,
                                               num_blocks, &compressed_buf_);
@@ -415,7 +416,7 @@
                         return data;
                     } else {
                         if (!compressor_) {
-                            compressor_ = ICompressor::Create(compression_);
+                            compressor_ = ICompressor::Create(compression_, header_.block_size);
                         }
 
                         auto data = compressor_->Compress(iter, header_.block_size);