Snap for 10786078 from a7c78d1aa667fdf3149878e90a23e4c1cd6cdc49 to mainline-media-release

Change-Id: I32dbcae2651ce53960abd9cf5c12bcf645f076f4
diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp
index 5deba65..ddda648 100644
--- a/fs_mgr/libfiemap/Android.bp
+++ b/fs_mgr/libfiemap/Android.bp
@@ -93,6 +93,9 @@
     test_options: {
         min_shipping_api_level: 29,
     },
+    header_libs: [
+        "libstorage_literals_headers",
+    ],
     require_root: true,
 }
 
diff --git a/fs_mgr/libfiemap/fiemap_writer_test.cpp b/fs_mgr/libfiemap/fiemap_writer_test.cpp
index c65481b..bd97a78 100644
--- a/fs_mgr/libfiemap/fiemap_writer_test.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer_test.cpp
@@ -22,21 +22,25 @@
 #include <string.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
+#include <sys/statvfs.h>
 #include <sys/types.h>
 #include <sys/vfs.h>
 #include <unistd.h>
 
 #include <string>
+#include <utility>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
+#include <fstab/fstab.h>
 #include <gtest/gtest.h>
 #include <libdm/loop_control.h>
 #include <libfiemap/fiemap_writer.h>
 #include <libfiemap/split_fiemap_writer.h>
 #include <libgsi/libgsi.h>
+#include <storage_literals/storage_literals.h>
 
 #include "utility.h"
 
@@ -46,6 +50,7 @@
 using namespace std;
 using namespace std::string_literals;
 using namespace android::fiemap;
+using namespace android::storage_literals;
 using unique_fd = android::base::unique_fd;
 using LoopDevice = android::dm::LoopDevice;
 
@@ -427,90 +432,123 @@
     ASSERT_FALSE(ptr->Write(buffer.get(), kSize));
 }
 
-class VerifyBlockWritesExt4 : public ::testing::Test {
+// Get max file size and free space.
+std::pair<uint64_t, uint64_t> GetBigFileLimit(const std::string& mount_point) {
+    struct statvfs fs;
+    if (statvfs(mount_point.c_str(), &fs) < 0) {
+        PLOG(ERROR) << "statfs failed";
+        return {0, 0};
+    }
+
+    auto fs_limit = static_cast<uint64_t>(fs.f_blocks) * (fs.f_bsize - 1);
+    auto fs_free = static_cast<uint64_t>(fs.f_bfree) * fs.f_bsize;
+
+    LOG(INFO) << "Big file limit: " << fs_limit << ", free space: " << fs_free;
+
+    return {fs_limit, fs_free};
+}
+
+class FsTest : public ::testing::Test {
+  protected:
     // 2GB Filesystem and 4k block size by default
     static constexpr uint64_t block_size = 4096;
-    static constexpr uint64_t fs_size = 2147483648;
+    static constexpr uint64_t fs_size = 64 * 1024 * 1024;
 
-  protected:
-    void SetUp() override {
-        fs_path = std::string(getenv("TMPDIR")) + "/ext4_2G.img";
+    void SetUp() {
+        android::fs_mgr::Fstab fstab;
+        ASSERT_TRUE(android::fs_mgr::ReadFstabFromFile("/proc/mounts", &fstab));
+
+        ASSERT_EQ(access(tmpdir_.path, F_OK), 0);
+        fs_path_ = tmpdir_.path + "/fs_image"s;
+        mntpoint_ = tmpdir_.path + "/mnt_point"s;
+
+        auto entry = android::fs_mgr::GetEntryForMountPoint(&fstab, "/data");
+        ASSERT_NE(entry, nullptr);
+        if (entry->fs_type == "ext4") {
+            SetUpExt4();
+        } else if (entry->fs_type == "f2fs") {
+            SetUpF2fs();
+        } else {
+            FAIL() << "Unrecognized fs_type: " << entry->fs_type;
+        }
+    }
+
+    void SetUpExt4() {
         uint64_t count = fs_size / block_size;
         std::string dd_cmd =
                 ::android::base::StringPrintf("/system/bin/dd if=/dev/zero of=%s bs=%" PRIu64
                                               " count=%" PRIu64 " > /dev/null 2>&1",
-                                              fs_path.c_str(), block_size, count);
+                                              fs_path_.c_str(), block_size, count);
         std::string mkfs_cmd =
-                ::android::base::StringPrintf("/system/bin/mkfs.ext4 -q %s", fs_path.c_str());
+                ::android::base::StringPrintf("/system/bin/mkfs.ext4 -q %s", fs_path_.c_str());
         // create mount point
-        mntpoint = std::string(getenv("TMPDIR")) + "/fiemap_mnt";
-        ASSERT_EQ(mkdir(mntpoint.c_str(), S_IRWXU), 0);
+        ASSERT_EQ(mkdir(mntpoint_.c_str(), S_IRWXU), 0);
         // create file for the file system
         int ret = system(dd_cmd.c_str());
         ASSERT_EQ(ret, 0);
         // Get and attach a loop device to the filesystem we created
-        LoopDevice loop_dev(fs_path, 10s);
+        LoopDevice loop_dev(fs_path_, 10s);
         ASSERT_TRUE(loop_dev.valid());
         // create file system
         ret = system(mkfs_cmd.c_str());
         ASSERT_EQ(ret, 0);
 
         // mount the file system
-        ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "ext4", 0, nullptr), 0);
+        ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint_.c_str(), "ext4", 0, nullptr), 0);
     }
 
-    void TearDown() override {
-        umount(mntpoint.c_str());
-        rmdir(mntpoint.c_str());
-        unlink(fs_path.c_str());
-    }
-
-    std::string mntpoint;
-    std::string fs_path;
-};
-
-class VerifyBlockWritesF2fs : public ::testing::Test {
-    // 2GB Filesystem and 4k block size by default
-    static constexpr uint64_t block_size = 4096;
-    static constexpr uint64_t fs_size = 2147483648;
-
-  protected:
-    void SetUp() override {
-        fs_path = std::string(getenv("TMPDIR")) + "/f2fs_2G.img";
+    void SetUpF2fs() {
         uint64_t count = fs_size / block_size;
         std::string dd_cmd =
                 ::android::base::StringPrintf("/system/bin/dd if=/dev/zero of=%s bs=%" PRIu64
                                               " count=%" PRIu64 " > /dev/null 2>&1",
-                                              fs_path.c_str(), block_size, count);
+                                              fs_path_.c_str(), block_size, count);
         std::string mkfs_cmd =
-                ::android::base::StringPrintf("/system/bin/make_f2fs -q %s", fs_path.c_str());
+                ::android::base::StringPrintf("/system/bin/make_f2fs -q %s", fs_path_.c_str());
         // create mount point
-        mntpoint = std::string(getenv("TMPDIR")) + "/fiemap_mnt";
-        ASSERT_EQ(mkdir(mntpoint.c_str(), S_IRWXU), 0);
+        ASSERT_EQ(mkdir(mntpoint_.c_str(), S_IRWXU), 0);
         // create file for the file system
         int ret = system(dd_cmd.c_str());
         ASSERT_EQ(ret, 0);
         // Get and attach a loop device to the filesystem we created
-        LoopDevice loop_dev(fs_path, 10s);
+        LoopDevice loop_dev(fs_path_, 10s);
         ASSERT_TRUE(loop_dev.valid());
         // create file system
         ret = system(mkfs_cmd.c_str());
         ASSERT_EQ(ret, 0);
 
         // mount the file system
-        ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "f2fs", 0, nullptr), 0);
+        ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint_.c_str(), "f2fs", 0, nullptr), 0);
     }
 
     void TearDown() override {
-        umount(mntpoint.c_str());
-        rmdir(mntpoint.c_str());
-        unlink(fs_path.c_str());
+        umount(mntpoint_.c_str());
+        rmdir(mntpoint_.c_str());
+        unlink(fs_path_.c_str());
     }
 
-    std::string mntpoint;
-    std::string fs_path;
+    TemporaryDir tmpdir_;
+    std::string mntpoint_;
+    std::string fs_path_;
 };
 
+TEST_F(FsTest, LowSpaceError) {
+    auto limits = GetBigFileLimit(mntpoint_);
+    ASSERT_GE(limits.first, 0);
+
+    FiemapUniquePtr ptr;
+
+    auto test_file = mntpoint_ + "/big_file";
+    auto status = FiemapWriter::Open(test_file, limits.first, &ptr);
+    ASSERT_FALSE(status.is_ok());
+    ASSERT_EQ(status.error_code(), FiemapStatus::ErrorCode::NO_SPACE);
+
+    // Also test for EFBIG.
+    status = FiemapWriter::Open(test_file, 16_TiB, &ptr);
+    ASSERT_FALSE(status.is_ok());
+    ASSERT_NE(status.error_code(), FiemapStatus::ErrorCode::NO_SPACE);
+}
+
 bool DetermineBlockSize() {
     struct statfs s;
     if (statfs(gTestDir.c_str(), &s)) {
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 460d49d..ce75a54 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -2312,32 +2312,6 @@
             << "FinishedSnapshotWrites should detect overflow of CoW device.";
 }
 
-TEST_F(SnapshotUpdateTest, LowSpace) {
-    static constexpr auto kMaxFree = 10_MiB;
-    auto userdata = std::make_unique<LowSpaceUserdata>();
-    ASSERT_TRUE(userdata->Init(kMaxFree));
-
-    // Grow all partitions to 10_MiB, total 30_MiB. This requires 30 MiB of CoW space. After
-    // using the empty space in super (< 1 MiB), it uses 30 MiB of /userdata space.
-    constexpr uint64_t partition_size = 10_MiB;
-    SetSize(sys_, partition_size);
-    SetSize(vnd_, partition_size);
-    SetSize(prd_, partition_size);
-    sys_->set_estimate_cow_size(partition_size);
-    vnd_->set_estimate_cow_size(partition_size);
-    prd_->set_estimate_cow_size(partition_size);
-
-    AddOperationForPartitions();
-
-    // Execute the update.
-    ASSERT_TRUE(sm->BeginUpdate());
-    auto res = sm->CreateUpdateSnapshots(manifest_);
-    ASSERT_FALSE(res);
-    ASSERT_EQ(Return::ErrorCode::NO_SPACE, res.error_code());
-    ASSERT_GE(res.required_size(), 14_MiB);
-    ASSERT_LT(res.required_size(), 40_MiB);
-}
-
 TEST_F(SnapshotUpdateTest, AddPartition) {
     group_->add_partition_names("dlkm");
 
@@ -2699,50 +2673,6 @@
                                     "Merge"s;
                          });
 
-class ImageManagerTest : public SnapshotTest {
-  protected:
-    void SetUp() override {
-        SKIP_IF_NON_VIRTUAL_AB();
-        SnapshotTest::SetUp();
-    }
-    void TearDown() override {
-        RETURN_IF_NON_VIRTUAL_AB();
-        CleanUp();
-    }
-    void CleanUp() {
-        if (!image_manager_) {
-            return;
-        }
-        EXPECT_TRUE(!image_manager_->BackingImageExists(kImageName) ||
-                    image_manager_->DeleteBackingImage(kImageName));
-    }
-
-    static constexpr const char* kImageName = "my_image";
-};
-
-TEST_F(ImageManagerTest, CreateImageNoSpace) {
-    bool at_least_one_failure = false;
-    for (uint64_t size = 1_MiB; size <= 512_MiB; size *= 2) {
-        auto userdata = std::make_unique<LowSpaceUserdata>();
-        ASSERT_TRUE(userdata->Init(size));
-
-        uint64_t to_allocate = userdata->free_space() + userdata->bsize();
-
-        auto res = image_manager_->CreateBackingImage(kImageName, to_allocate,
-                                                      IImageManager::CREATE_IMAGE_DEFAULT);
-        if (!res) {
-            at_least_one_failure = true;
-        } else {
-            ASSERT_EQ(res.error_code(), FiemapStatus::ErrorCode::NO_SPACE) << res.string();
-        }
-
-        CleanUp();
-    }
-
-    ASSERT_TRUE(at_least_one_failure)
-            << "We should have failed to allocate at least one over-sized image";
-}
-
 bool Mkdir(const std::string& path) {
     if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
         std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
diff --git a/fs_mgr/libstorage_literals/storage_literals/storage_literals.h b/fs_mgr/libstorage_literals/storage_literals/storage_literals.h
index ac0dfbd..bbeabd5 100644
--- a/fs_mgr/libstorage_literals/storage_literals/storage_literals.h
+++ b/fs_mgr/libstorage_literals/storage_literals/storage_literals.h
@@ -37,6 +37,7 @@
 using KiB = Size<10>;
 using MiB = Size<20>;
 using GiB = Size<30>;
+using TiB = Size<40>;
 
 constexpr B operator""_B(unsigned long long v) {  // NOLINT
     return B{v};
@@ -54,6 +55,10 @@
     return GiB{v};
 }
 
+constexpr TiB operator""_TiB(unsigned long long v) {  // NOLINT
+    return TiB{v};
+}
+
 template <typename Dest, typename Src>
 constexpr Dest size_cast(Src src) {
     if (Src::power < Dest::power) {
@@ -69,6 +74,7 @@
 static_assert(1_KiB == 1 << 10);
 static_assert(1_MiB == 1 << 20);
 static_assert(1_GiB == 1 << 30);
+static_assert(1_TiB == 1ULL << 40);
 static_assert(size_cast<KiB>(1_B).count() == 0);
 static_assert(size_cast<KiB>(1024_B).count() == 1);
 static_assert(size_cast<KiB>(1_MiB).count() == 1024);