Merge changes If7209ec4,Ia27f7f3c,Ib6adbe37

* changes:
  fd_server: support open file by path at a dir fd
  Implement root directory as a ReadonlyDirectory
  Fix incorrect inode assignment for remote directory
diff --git a/tests/benchmark/Android.bp b/tests/benchmark/Android.bp
new file mode 100644
index 0000000..1826524
--- /dev/null
+++ b/tests/benchmark/Android.bp
@@ -0,0 +1,19 @@
+cc_binary {
+    name: "fs_benchmark",
+    static_executable: true,
+    static_libs: ["libbase"],
+    srcs: ["fs_benchmark.cpp"],
+}
+
+cc_library_shared {
+    name: "empty_payload",
+    srcs: ["empty_payload.cpp"],
+}
+
+android_app {
+    name: "MicrodroidFilesystemBenchmarkApp",
+    srcs: [],
+    jni_libs: ["empty_payload"],
+    platform_apis: true,
+    use_embedded_native_libs: true,
+}
diff --git a/tests/benchmark/AndroidManifest.xml b/tests/benchmark/AndroidManifest.xml
new file mode 100644
index 0000000..9fd7347
--- /dev/null
+++ b/tests/benchmark/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.android.microdroid.benchmark">
+    <application android:label="Microdroid Filesystem Benchmark" />
+</manifest>
diff --git a/tests/benchmark/assets/benchmark.pem b/tests/benchmark/assets/benchmark.pem
new file mode 100644
index 0000000..2716fde
--- /dev/null
+++ b/tests/benchmark/assets/benchmark.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCsXMc0YBu8ch0E
+ACd9xchbrAHulBYggzsQ9sEj6paC211QfRoYt2kCukAvj4uqutIBACLO44FPUfjf
+Pzh6woSXU8NdLiMR23Quyg8JChChdTvvl83aTCnKdUAO8YnmjWxdebuIeisv0QGQ
+VbZWhZP+VTXWBgbBQ426Klkx/GZXBGT5TpKBf4/Y9x3iOaYKSK0F5uSbl5BSD9rG
+iizWQAgBe2TfyzYQFOdjjiu6/sJ92d/Y5bVWo4efhWg8ZPyhi6oLyfnm/hbn5t3H
+IIYptmdoqFy2xgZf++EWoPwfvaG3YB6mmRwt/bvuGyab43duzSCjR6Sj93p7Y3Zb
+l4vdIG9TAgMBAAECggEADO/dx9Ga41cRVHaKgEczFaZgcr7Mtl4DNe+/aWm3KFU8
+uMjbB5XknN7L6IX2rrbdAlQ3SJ4M255EdsUxAQ3Ok+kmlbzbxwBYxRZHcJ8/xk6d
+VAtp2QO0c0y/pR9+AT8GLjHv4HuC+FDQtDuqtu3JwOI2az0Cjsj6P0nkbfsK12cO
+eKQnCH8dYSvmdPWF2GimBgJVhsfoeY9gQ44aR9sMSSwWMO7M58CkRuur9QvKYB/C
+fLjcA7dqodmLNMbiLAe/RWfg+WfdR9DUgbK3zB2h+2+qFyFCfMFt03I+DkVzg/ej
+ICNmgv4D9eRJaKdIXaCKA8FqHqQN+/a6cmDUi8qQ6QKBgQDbnrkxJAoLJ6gPBFOu
+Eml/XVczll8F4EEyQz0uPBgADkE5CV6Zh4gaBMj3b6iuUq7sQRldeDb3C/g5zcUZ
+U940gmzlJv4FPf0itJ46JNkIrCSuf0/NhDb2qIvrb/j+VTzd350YgMIG34B9tLxu
+W+eHuDTDSMsS0YZHAVZzGmhFRQKBgQDI6gisOKgpp4KZnvqxJCJ/54PMO6Kks7Oa
+4ZVyc8iTn1B6k+njOy98xzk29pI3+o1v822WImwGs0njAUcAPm7jPEer657rva8C
+ZVmSzme/YHfxhOI7QGzGyXdmh+3Da4ywAUwgfPY7b+lv+I0J9pcijpIh1ayApKy2
+I32TIjZvtwKBgQDGzLrenLzqtA8Q6N3GqKwOurOA4xFJBGJ/2RW8kHE5O64Wr0CO
+wXyV8NbqBI0wn2/wNE19qqA2qQMdcAKGlsCBz747ADzZCe/mRpEkGM7NZuYdfukC
+JDiMtq1RhZ5iu03Jme1ejM8V4aMyJzSawV6oIDrCu1X3xupBxBg5QSI58QKBgQCx
+/Ts/r1WyyTZW99NpWPTDUQuew/obZSOpA03NPiukNBAs95rNdqJkLW5PdfMlam8g
+jYw45DfFW9IKLBiFa8n6v21TLgL1H27KdZT8DKU2krTPnwR4r2NuXA7OI3+Mj1vs
+lMmnQm01TLiGPLBd8joEID/vf4c51Ck5lolp7nZBUwKBgQCmS5R2fsH0XYCMvfWR
+hHUre/zxNMj6+FrxiglecdJLPAAIEUmP2No/KRnLezi36TdL9aXGLBhTt9KQeQnv
+eoKIUFkYr6kTP/mXG9LM7yqE+ic37M4MZ2qL7DE8MSASy/aBKruueyLEUSWvjGxd
+aBW8JQ/zbcsdZKwV1as6St5kyQ==
+-----END PRIVATE KEY-----
diff --git a/tests/benchmark/assets/benchmark.pk8 b/tests/benchmark/assets/benchmark.pk8
new file mode 100644
index 0000000..a78fa9b
--- /dev/null
+++ b/tests/benchmark/assets/benchmark.pk8
Binary files differ
diff --git a/tests/benchmark/assets/benchmark.x509.der b/tests/benchmark/assets/benchmark.x509.der
new file mode 100644
index 0000000..d137bc0
--- /dev/null
+++ b/tests/benchmark/assets/benchmark.x509.der
Binary files differ
diff --git a/tests/benchmark/assets/benchmark.x509.pem b/tests/benchmark/assets/benchmark.x509.pem
new file mode 100644
index 0000000..7bc794b
--- /dev/null
+++ b/tests/benchmark/assets/benchmark.x509.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIECzCCAvOgAwIBAgIUXL3rcLOhlqZ9IDu04sF+FGo3OtIwDQYJKoZIhvcNAQEL
+BQAwgZQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMRAwDgYDVQQDDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFu
+ZHJvaWQuY29tMB4XDTIxMTAyNzEzNDE1NloXDTQ5MDMxNDEzNDE1NlowgZQxCzAJ
+BgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFp
+biBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMRAwDgYD
+VQQDDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArFzHNGAbvHIdBAAnfcXI
+W6wB7pQWIIM7EPbBI+qWgttdUH0aGLdpArpAL4+LqrrSAQAizuOBT1H43z84esKE
+l1PDXS4jEdt0LsoPCQoQoXU775fN2kwpynVADvGJ5o1sXXm7iHorL9EBkFW2VoWT
+/lU11gYGwUONuipZMfxmVwRk+U6SgX+P2Pcd4jmmCkitBebkm5eQUg/axoos1kAI
+AXtk38s2EBTnY44ruv7Cfdnf2OW1VqOHn4VoPGT8oYuqC8n55v4W5+bdxyCGKbZn
+aKhctsYGX/vhFqD8H72ht2AeppkcLf277hsmm+N3bs0go0eko/d6e2N2W5eL3SBv
+UwIDAQABo1MwUTAdBgNVHQ4EFgQU8eS6/fiyZMqPN1erLU8POJHci4swHwYDVR0j
+BBgwFoAU8eS6/fiyZMqPN1erLU8POJHci4swDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAQEAagHQT+tZ5RE2V9U/3gXdqyQzpIjIAWBdA1HJ0obi+mqr
+n5BtftKHK2li/f6jp64oCxwBOtZZEWj8J4m53EWunG9oktjfiCq1wKASdfrhSN6J
+hz+YSBURsrrDOVzVCcKgzwlEgYYMsAt+NnGGp9UlSaJMpQSghrDNkKmDLB1zfkN1
+sRG71UbqqxSun/3k0HcwWIRy6WTDXoPeyYWuCaksdzqPHMvn0bbgf1Jw6jI5UNXG
+3ZSteqhLseS6jhlYOmfLaINHpBfdZXdzqsEjlg6Qt2pCNaRfVp2+fIfNjsWhrfOJ
+8uoz3I/u5Nd3S2ET/jYqpqsB3g9ngjbilclKYjL1bg==
+-----END CERTIFICATE-----
diff --git a/tests/benchmark/assets/vm_config.json b/tests/benchmark/assets/vm_config.json
new file mode 100644
index 0000000..d431877
--- /dev/null
+++ b/tests/benchmark/assets/vm_config.json
@@ -0,0 +1,11 @@
+{
+  "os": {
+    "name": "microdroid"
+  },
+  "task": {
+    "type": "microdroid_launcher",
+    "command": "empty_payload.so",
+    "args": []
+  }
+}
+
diff --git a/tests/benchmark/benchmark_example.sh b/tests/benchmark/benchmark_example.sh
new file mode 100755
index 0000000..49cf258
--- /dev/null
+++ b/tests/benchmark/benchmark_example.sh
@@ -0,0 +1,61 @@
+# This script runs 256 MB file benchmark, both on host and on authfs.
+# Usage: after connecting the device with adb, run:
+# $ packages/modules/Virtualization/tests/benchmark/benchmark_example.sh <target> (e.g. aosp_oriole_pkvm-userdebug)
+
+set -e
+
+# Prerequisite: we need root to flush disk cache.
+adb root
+
+# 1. Build needed artifacts, and install it to device
+source build/make/rbesetup.sh
+lunch $1
+m fs_benchmark MicrodroidFilesystemBenchmarkApp fsverity
+adb push $OUT/system/bin/fs_benchmark /data/local/tmp
+adb install $OUT/system/app/MicrodroidFilesystemBenchmarkApp/MicrodroidFilesystemBenchmarkApp.apk
+
+# 2. Generate testcases
+# /data/local/tmp/testcase: 256 MB, signed by fsverity.
+# /data/local/tmp/testcase2: empty file, used for authfs write test.
+adb shell 'rm -rf /data/local/tmp/virt /data/local/tmp/testcase*'
+adb shell 'mkdir -p /data/local/tmp/virt'
+dd if=/dev/zero of=/tmp/testcase bs=1048576 count=256
+fsverity sign /tmp/testcase /tmp/testcase.fsv_sig --key=packages/modules/Virtualization/tests/benchmark/assets/benchmark.pem \
+    --out-merkle-tree=/tmp/testcase.merkle_dump --cert=packages/modules/Virtualization/tests/benchmark/assets/benchmark.x509.pem
+adb shell 'dd if=/dev/zero of=/data/local/tmp/testcase bs=1048576 count=256'
+adb push /tmp/testcase.fsv_sig /tmp/testcase.merkle_dump /data/local/tmp
+
+# 3. Run fd_server from host
+adb shell 'exec 3</data/local/tmp/testcase 4</data/local/tmp/testcase.merkle_dump 5</data/local/tmp/testcase.fsv_sig 6</data/local/tmp/testcase 7<>/data/local/tmp/testcase2 /apex/com.android.virt/bin/fd_server --ro-fds 3:4:5 --ro-fds 6 --rw-fds 7' &
+
+# 4. Run VM and get the CID
+result=$(adb shell "/apex/com.android.virt/bin/vm run-app --debug full --daemonize --log /data/local/tmp/virt/log.txt $(adb shell pm path com.android.microdroid.benchmark | cut -d':' -f2) /data/local/tmp/virt/MicrodroidFilesystemBenchmarkApp.apk.idsig /data/local/tmp/virt/instance.img assets/vm_config.json")
+cid=$(echo $result | grep -P "with CID \d+" --only-matching --color=none | cut -d' ' -f3)
+echo "CID IS $cid"
+
+# 5. Run host tests
+echo "Running host read/write test..."
+adb shell 'dd if=/dev/zero of=/data/local/tmp/testcase_host bs=1048576 count=256'
+adb shell '/data/local/tmp/fs_benchmark /data/local/tmp/testcase_host 268435456 both 5'
+
+# 6. Connect to the VM
+# We are cheating here. The VM is expected to finish booting, while the host tests are running.
+adb forward tcp:8000 vsock:$cid:5555
+adb connect localhost:8000
+adb -s localhost:8000 root
+sleep 10
+
+# 7. Install artifacts and run authfs
+adb -s localhost:8000 push $OUT/system/bin/fs_benchmark /data/local/tmp
+adb -s localhost:8000 shell "mkdir -p /data/local/tmp/authfs"
+adb -s localhost:8000 shell "/system/bin/authfs /data/local/tmp/authfs --cid 2 --remote-ro-file 3:/mnt/apk/assets/benchmark.x509.der --remote-ro-file-unverified 6 --remote-new-rw-file 7" &
+
+# 8. Run guest tests
+echo "Running guest block device read test..."
+adb -s localhost:8000 shell "/data/local/tmp/fs_benchmark /dev/block/vda $(adb -s localhost:8000 shell blockdev --getsize64 /dev/block/vda) read 5"
+echo "Running guest authfs read test..."
+adb -s localhost:8000 shell "/data/local/tmp/fs_benchmark /data/local/tmp/authfs/3 268435456 read 5"
+echo "Running guest authfs unverified read test..."
+adb -s localhost:8000 shell "/data/local/tmp/fs_benchmark /data/local/tmp/authfs/6 268435456 read 5"
+echo "Running guest authfs write test..."
+adb -s localhost:8000 shell "/data/local/tmp/fs_benchmark /data/local/tmp/authfs/7 268435456 write 5"
diff --git a/tests/benchmark/empty_payload.cpp b/tests/benchmark/empty_payload.cpp
new file mode 100644
index 0000000..afcd653
--- /dev/null
+++ b/tests/benchmark/empty_payload.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern "C" int android_native_main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
+    // do nothing
+    return 0;
+}
diff --git a/tests/benchmark/fs_benchmark.cpp b/tests/benchmark/fs_benchmark.cpp
new file mode 100644
index 0000000..583480e
--- /dev/null
+++ b/tests/benchmark/fs_benchmark.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+#include <linux/vm_sockets.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cerrno>
+#include <cinttypes>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <random>
+#include <string>
+#include <vector>
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+using android::base::unique_fd;
+
+namespace {
+
+constexpr int kBlockSize = 4096;
+
+[[noreturn]] void PrintUsage(const char* exe_name) {
+    std::printf("Usage: %s path size (read|write|both) [rounds]\n", exe_name);
+    std::exit(EXIT_FAILURE);
+}
+
+void DropCache() {
+    system("echo 1 > /proc/sys/vm/drop_caches");
+}
+
+struct BenchmarkResult {
+    struct timespec elapsed;
+    std::uint64_t size;
+};
+
+enum class BenchmarkOption {
+    READ = 0,
+    WRITE = 1,
+    RANDREAD = 2,
+    RANDWRITE = 3,
+};
+
+Result<BenchmarkResult> runTest(const char* path, BenchmarkOption option, std::uint64_t size) {
+    bool is_read = (option == BenchmarkOption::READ || option == BenchmarkOption::RANDREAD);
+    bool is_rand = (option == BenchmarkOption::RANDREAD || option == BenchmarkOption::RANDWRITE);
+
+    unique_fd fd(open(path, is_read ? O_RDONLY : O_WRONLY | O_CREAT, 0644));
+    if (fd.get() == -1) {
+        return ErrnoError() << "opening " << path << " failed";
+    }
+
+    uint64_t block_count = (size + kBlockSize - 1) / kBlockSize;
+    std::vector<uint64_t> offsets;
+    if (is_rand) {
+        std::mt19937 rd{std::random_device{}()};
+        offsets.reserve(block_count);
+        for (uint64_t i = 0; i < block_count; i++) offsets.push_back(i * kBlockSize);
+        std::shuffle(offsets.begin(), offsets.end(), rd);
+    }
+
+    uint64_t total_processed = 0;
+    char buf[kBlockSize] = {};
+
+    struct timespec start;
+    if (clock_gettime(CLOCK_REALTIME, &start) < 0) {
+        return ErrnoError() << "failed to get start time";
+    }
+
+    for (uint64_t i = 0; i < block_count; i++) {
+        if (!offsets.empty()) {
+            if (lseek(fd.get(), offsets[i], SEEK_SET) == -1) {
+                return ErrnoError() << "failed to lseek";
+            }
+        }
+
+        auto ret = is_read ? read(fd.get(), buf, kBlockSize) : write(fd.get(), buf, kBlockSize);
+        if (ret == 0) {
+            return Error() << "unexpected end of file";
+        } else if (ret == -1) {
+            return ErrnoError() << "file io failed";
+        }
+        total_processed += ret;
+    }
+
+    struct timespec stop;
+    if (clock_gettime(CLOCK_REALTIME, &stop) < 0) {
+        return ErrnoError() << "failed to get finish time";
+    }
+
+    struct timespec elapsed;
+    if ((stop.tv_nsec - start.tv_nsec) < 0) {
+        elapsed.tv_sec = stop.tv_sec - start.tv_sec - 1;
+        elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec + 1000000000;
+    } else {
+        elapsed.tv_sec = stop.tv_sec - start.tv_sec;
+        elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
+    }
+
+    return BenchmarkResult{elapsed, total_processed};
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+    // without this, stdout isn't immediately flushed when running via "adb shell"
+    std::setvbuf(stdout, nullptr, _IONBF, 0);
+    std::setvbuf(stderr, nullptr, _IONBF, 0);
+
+    if (argc < 4 || argc > 5) {
+        PrintUsage(argv[0]);
+    }
+
+    const char* path = argv[1];
+
+    std::uint64_t size = std::strtoull(argv[2], nullptr, 0);
+    if (size == 0 || size == UINT64_MAX) {
+        std::fprintf(stderr, "invalid size %s\n", argv[1]);
+        PrintUsage(argv[0]);
+    }
+
+    std::vector<std::pair<BenchmarkOption, std::string>> benchmarkList;
+    if (strcmp(argv[3], "read") != 0) {
+        benchmarkList.emplace_back(BenchmarkOption::WRITE, "write");
+        benchmarkList.emplace_back(BenchmarkOption::RANDWRITE, "randwrite");
+    }
+    if (strcmp(argv[3], "write") != 0) {
+        benchmarkList.emplace_back(BenchmarkOption::READ, "read");
+        benchmarkList.emplace_back(BenchmarkOption::RANDREAD, "randread");
+    }
+
+    std::shuffle(benchmarkList.begin(), benchmarkList.end(), std::mt19937{std::random_device{}()});
+
+    int rounds = 1;
+    if (argc == 5) {
+        rounds = std::atoi(argv[4]);
+        if (rounds <= 0) {
+            std::fprintf(stderr, "invalid round %s\n", argv[4]);
+            PrintUsage(argv[0]);
+        }
+    }
+
+    for (auto [option, name] : benchmarkList) {
+        std::printf("%s test:\n", name.c_str());
+
+        for (int i = 0; i < rounds; i++) {
+            DropCache();
+            auto res = runTest(path, option, size);
+            if (!res.ok()) {
+                std::fprintf(stderr, "Error while benchmarking: %s\n",
+                             res.error().message().c_str());
+                return EXIT_FAILURE;
+            }
+
+            double elapsed_time = res->elapsed.tv_sec + res->elapsed.tv_nsec / 1e9;
+            std::printf("total %" PRIu64 " bytes, took %.3g seconds ", res->size, elapsed_time);
+
+            double speed = res->size / elapsed_time;
+            const char* unit;
+            if (speed >= 1000) {
+                speed /= 1024;
+                unit = "KB";
+            }
+            if (speed >= 1000) {
+                speed /= 1024;
+                unit = "MB";
+            }
+            if (speed >= 1000) {
+                speed /= 1024;
+                unit = "GB";
+            }
+            std::printf("(%.3g %s/s)\n", speed, unit);
+        }
+        std::printf("\n");
+    }
+}
diff --git a/virtualizationservice/src/composite.rs b/virtualizationservice/src/composite.rs
index 40c7e5e..cb814f3 100644
--- a/virtualizationservice/src/composite.rs
+++ b/virtualizationservice/src/composite.rs
@@ -16,7 +16,9 @@
 
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::Partition::Partition;
 use anyhow::{anyhow, Context, Error};
-use disk::{create_composite_disk, create_disk_file, ImagePartitionType, PartitionInfo};
+use disk::{
+    create_composite_disk, create_disk_file, ImagePartitionType, PartitionInfo, MAX_NESTING_DEPTH,
+};
 use std::fs::{File, OpenOptions};
 use std::os::unix::io::AsRawFd;
 use std::path::{Path, PathBuf};
@@ -119,7 +121,7 @@
 /// This will work for raw, QCOW2, composite and Android sparse images.
 fn get_partition_size(partition: &File) -> Result<u64, Error> {
     // TODO: Use `context` once disk::Error implements std::error::Error.
-    Ok(create_disk_file(partition.try_clone()?)
+    Ok(create_disk_file(partition.try_clone()?, MAX_NESTING_DEPTH)
         .map_err(|e| anyhow!("Failed to open partition image: {}", e))?
         .get_len()?)
 }