Merge "Convert fs_mgr_swapon_all() to use the new Fstab struct"
diff --git a/adb/Android.bp b/adb/Android.bp
index e994075..ae8e386 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -25,7 +25,6 @@
         "-Wvla",
     ],
     rtti: true,
-    cpp_std: "gnu++17",
 
     use_version_lib: true,
 
@@ -72,7 +71,7 @@
                 "-DUNICODE=1",
                 "-D_UNICODE=1",
 
-                // -std=gnu++11 doesn't set _GNU_SOURCE on Windows.
+                // Unlike on Linux, -std=gnu++ doesn't set _GNU_SOURCE on Windows.
                 "-D_GNU_SOURCE",
 
                 // MinGW hides some things behind _POSIX_SOURCE.
diff --git a/adb/NOTICE b/adb/NOTICE
index ff47c95..9ffcc08 100644
--- a/adb/NOTICE
+++ b/adb/NOTICE
@@ -189,63 +189,3 @@
 
    END OF TERMS AND CONDITIONS
 
-------------------------------------------------------------
-libwinpthread license:
-------------------------------------------------------------
-Copyright (c) 2011 mingw-w64 project
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
-
-/*
- * Parts of this library are derived by:
- *
- * Posix Threads library for Microsoft Windows
- *
- * Use at own risk, there is no implied warranty to this code.
- * It uses undocumented features of Microsoft Windows that can change
- * at any time in the future.
- *
- * (C) 2010 Lockless Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- *
- *  * Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *  * Neither the name of Lockless Inc. nor the names of its contributors may be
- *    used to endorse or promote products derived from this software without
- *    specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
diff --git a/adb/transport.cpp b/adb/transport.cpp
index c2d4917..76a31ce 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1009,14 +1009,11 @@
 const FeatureSet& supported_features() {
     // Local static allocation to avoid global non-POD variables.
     static const FeatureSet* features = new FeatureSet{
-        kFeatureShell2, kFeatureCmd, kFeatureStat2, kFeatureFixedPushMkdir,
-#if ADB_HOST
-                kFeatureApex
-#endif
-        // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
-        // to know about. Otherwise, the client can be stuck running an old
-        // version of the server even after upgrading their copy of adb.
-        // (http://b/24370690)
+            kFeatureShell2, kFeatureCmd, kFeatureStat2, kFeatureFixedPushMkdir, kFeatureApex
+            // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
+            // to know about. Otherwise, the client can be stuck running an old
+            // version of the server even after upgrading their copy of adb.
+            // (http://b/24370690)
     };
 
     return *features;
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 4e3879b..4e6c879 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <dirent.h>
 #include <fcntl.h>
 
 #if !defined(_WIN32)
@@ -231,3 +232,13 @@
 template <typename T>
 int close(const android::base::unique_fd_impl<T>&)
     __attribute__((__unavailable__("close called on unique_fd")));
+
+template <typename T>
+FILE* fdopen(const android::base::unique_fd_impl<T>&, const char* mode)
+    __attribute__((__unavailable__("fdopen takes ownership of the fd passed in; either dup the "
+                                   "unique_fd, or use android::base::Fdopen to pass ownership")));
+
+template <typename T>
+DIR* fdopendir(const android::base::unique_fd_impl<T>&) __attribute__((
+    __unavailable__("fdopendir takes ownership of the fd passed in; either dup the "
+                    "unique_fd, or use android::base::Fdopendir to pass ownership")));
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 03b3287..d9fae52 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -9,7 +9,6 @@
         "-Wno-nullability-completeness",
         "-Os",
     ],
-    cpp_std: "gnu++17",
 
     local_include_dirs: ["include"],
 }
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 8006c41..ead2105 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -144,8 +144,6 @@
     static_libs: [
         "libhealthhalutils",
     ],
-
-    cpp_std: "c++17",
 }
 
 cc_defaults {
@@ -212,7 +210,6 @@
     name: "libfastboot",
     defaults: ["fastboot_host_defaults"],
 
-    cpp_std: "c++17",
     srcs: [
         "bootimg_utils.cpp",
         "fastboot.cpp",
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index 7b99884..fbba631 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -153,6 +153,7 @@
         if (!FlashPartitionTable(super_name, *new_metadata.get())) {
             return device->WriteFail("Unable to flash new partition table");
         }
+        fs_mgr_overlayfs_teardown();
         return device->WriteOkay("Successfully flashed partition table");
     }
 
@@ -186,5 +187,6 @@
     if (!UpdateAllPartitionMetadata(super_name, *new_metadata.get())) {
         return device->WriteFail("Unable to write new partition table");
     }
+    fs_mgr_overlayfs_teardown();
     return device->WriteOkay("Successfully updated partition table");
 }
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index f150af3..99231ac 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -25,9 +25,6 @@
         "-Werror",
         "-Wno-unused-variable",
     ],
-    cppflags: [
-        "-std=gnu++1z",
-    ],
 }
 
 cc_library {
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
index d715d7b..2d42d6c 100644
--- a/fs_mgr/README.overlayfs.md
+++ b/fs_mgr/README.overlayfs.md
@@ -89,4 +89,9 @@
   if higher than 4.6.
 - *adb enable-verity* will free up overlayfs and as a bonus the
   device will be reverted pristine to before any content was updated.
+- If dynamic partitions runs out of space, resizing a logical
+  partition larger may fail because of the scratch partition.
+  If this happens, either fastboot flashall or adb enable-verity can
+  be used to clear scratch storage to permit the flash.
+  Then reinstate the overrides and continue.
 - File bugs or submit fixes for review.
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 3a21c0b..750ed71 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -82,6 +82,7 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
+using android::base::Realpath;
 using android::dm::DeviceMapper;
 using android::dm::DmDeviceState;
 using android::fs_mgr::AvbHandle;
@@ -100,7 +101,7 @@
     FS_STAT_FULL_MOUNT_FAILED = 0x0100,
     FS_STAT_E2FSCK_FAILED = 0x0200,
     FS_STAT_E2FSCK_FS_FIXED = 0x0400,
-    FS_STAT_EXT4_INVALID_MAGIC = 0x0800,
+    FS_STAT_INVALID_MAGIC = 0x0800,
     FS_STAT_TOGGLE_QUOTAS_FAILED = 0x10000,
     FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000,
     FS_STAT_ENABLE_ENCRYPTION_FAILED = 0x40000,
@@ -143,6 +144,18 @@
     return fs_type == "ext4" || fs_type == "ext3" || fs_type == "ext2";
 }
 
+static bool is_f2fs(const std::string& fs_type) {
+    return fs_type == "f2fs";
+}
+
+static std::string realpath(const char* blk_device) {
+    std::string real_path;
+    if (!Realpath(blk_device, &real_path)) {
+        real_path = blk_device;
+    }
+    return real_path;
+}
+
 static bool should_force_check(int fs_stat) {
     return fs_stat &
            (FS_STAT_E2FSCK_F_ALWAYS | FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED |
@@ -160,11 +173,12 @@
     const char* e2fsck_argv[] = {E2FSCK_BIN, "-y", blk_device};
     const char* e2fsck_forced_argv[] = {E2FSCK_BIN, "-f", "-y", blk_device};
 
+    if (*fs_stat & FS_STAT_INVALID_MAGIC) {  // will fail, so do not try
+        return;
+    }
+
     /* Check for the types of filesystems we know how to check */
     if (is_extfs(fs_type)) {
-        if (*fs_stat & FS_STAT_EXT4_INVALID_MAGIC) {  // will fail, so do not try
-            return;
-        }
         /*
          * First try to mount and unmount the filesystem.  We do this because
          * the kernel is more efficient than e2fsck in running the journal and
@@ -214,10 +228,10 @@
          * (e.g. recent SDK system images). Detect these and skip the check.
          */
         if (access(E2FSCK_BIN, X_OK)) {
-            LINFO << "Not running " << E2FSCK_BIN << " on " << blk_device
+            LINFO << "Not running " << E2FSCK_BIN << " on " << realpath(blk_device)
                   << " (executable not in system image)";
         } else {
-            LINFO << "Running " << E2FSCK_BIN << " on " << blk_device;
+            LINFO << "Running " << E2FSCK_BIN << " on " << realpath(blk_device);
             if (should_force_check(*fs_stat)) {
                 ret = android_fork_execvp_ext(
                     ARRAY_SIZE(e2fsck_forced_argv), const_cast<char**>(e2fsck_forced_argv), &status,
@@ -237,13 +251,9 @@
                 *fs_stat |= FS_STAT_E2FSCK_FS_FIXED;
             }
         }
-    } else if (!strcmp(fs_type, "f2fs")) {
-            const char *f2fs_fsck_argv[] = {
-                    F2FS_FSCK_BIN,
-                    "-a",
-                    blk_device
-            };
-        LINFO << "Running " << F2FS_FSCK_BIN << " -a " << blk_device;
+    } else if (is_f2fs(fs_type)) {
+        const char* f2fs_fsck_argv[] = {F2FS_FSCK_BIN, "-a", blk_device};
+        LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device);
 
         ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv),
                                       const_cast<char **>(f2fs_fsck_argv),
@@ -277,7 +287,7 @@
 }
 
 // Read the primary superblock from an ext4 filesystem.  On failure return
-// false.  If it's not an ext4 filesystem, also set FS_STAT_EXT4_INVALID_MAGIC.
+// false.  If it's not an ext4 filesystem, also set FS_STAT_INVALID_MAGIC.
 static bool read_ext4_superblock(const char* blk_device, struct ext4_super_block* sb, int* fs_stat) {
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC)));
 
@@ -294,7 +304,7 @@
     if (!is_ext4_superblock_valid(sb)) {
         LINFO << "Invalid ext4 superblock on '" << blk_device << "'";
         // not a valid fs, tune2fs, fsck, and mount  will all fail.
-        *fs_stat |= FS_STAT_EXT4_INVALID_MAGIC;
+        *fs_stat |= FS_STAT_INVALID_MAGIC;
         return false;
     }
     *fs_stat |= FS_STAT_IS_EXT4;
@@ -422,6 +432,36 @@
     }
 }
 
+// Read the primary superblock from an f2fs filesystem.  On failure return
+// false.  If it's not an f2fs filesystem, also set FS_STAT_INVALID_MAGIC.
+#define F2FS_BLKSIZE 4096
+#define F2FS_SUPER_OFFSET 1024
+static bool read_f2fs_superblock(const char* blk_device, int* fs_stat) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC)));
+    __le32 sb1, sb2;
+
+    if (fd < 0) {
+        PERROR << "Failed to open '" << blk_device << "'";
+        return false;
+    }
+
+    if (pread(fd, &sb1, sizeof(sb1), F2FS_SUPER_OFFSET) != sizeof(sb1)) {
+        PERROR << "Can't read '" << blk_device << "' superblock1";
+        return false;
+    }
+    if (pread(fd, &sb2, sizeof(sb2), F2FS_BLKSIZE + F2FS_SUPER_OFFSET) != sizeof(sb2)) {
+        PERROR << "Can't read '" << blk_device << "' superblock2";
+        return false;
+    }
+
+    if (sb1 != cpu_to_le32(F2FS_SUPER_MAGIC) && sb2 != cpu_to_le32(F2FS_SUPER_MAGIC)) {
+        LINFO << "Invalid f2fs superblock on '" << blk_device << "'";
+        *fs_stat |= FS_STAT_INVALID_MAGIC;
+        return false;
+    }
+    return true;
+}
+
 //
 // Prepare the filesystem on the given block device to be mounted.
 //
@@ -451,6 +491,10 @@
         } else {
             return fs_stat;
         }
+    } else if (is_f2fs(rec->fs_type)) {
+        if (!read_f2fs_superblock(blk_device, &fs_stat)) {
+            return fs_stat;
+        }
     }
 
     if ((rec->fs_mgr_flags & MF_CHECK) ||
@@ -617,9 +661,10 @@
             }
 
             int fs_stat = prepare_fs_for_mount(fstab->recs[i].blk_device, &fstab->recs[i]);
-            if (fs_stat & FS_STAT_EXT4_INVALID_MAGIC) {
-                LERROR << __FUNCTION__ << "(): skipping mount, invalid ext4, mountpoint="
-                       << fstab->recs[i].mount_point << " rec[" << i
+            if (fs_stat & FS_STAT_INVALID_MAGIC) {
+                LERROR << __FUNCTION__ << "(): skipping mount due to invalid magic, mountpoint="
+                       << fstab->recs[i].mount_point
+                       << " blk_dev=" << realpath(fstab->recs[i].blk_device) << " rec[" << i
                        << "].fs_type=" << fstab->recs[i].fs_type;
                 mount_errno = EINVAL;  // continue bootup for FDE
                 continue;
@@ -911,7 +956,7 @@
   private:
     bool UpdateCheckpointPartition(struct fstab_rec* rec) {
         if (fs_mgr_is_checkpoint_fs(rec)) {
-            if (!strcmp(rec->fs_type, "f2fs")) {
+            if (is_f2fs(rec->fs_type)) {
                 std::string opts(rec->fs_options);
 
                 opts += ",checkpoint=disable";
@@ -1002,7 +1047,7 @@
         /* Skip mounting the root partition, as it will already have been mounted */
         if (!strcmp(fstab->recs[i].mount_point, "/") ||
             !strcmp(fstab->recs[i].mount_point, "/system")) {
-            if ((fstab->recs[i].fs_mgr_flags & MS_RDONLY) != 0) {
+            if ((fstab->recs[i].flags & MS_RDONLY) != 0) {
                 fs_mgr_set_blk_ro(fstab->recs[i].blk_device);
             }
             continue;
@@ -1104,10 +1149,9 @@
              * at two different lines in the fstab.  Use the top one for formatting
              * as that is the preferred one.
              */
-            LERROR << __FUNCTION__ << "(): " << fstab->recs[top_idx].blk_device
-                   << " is wiped and " << fstab->recs[top_idx].mount_point
-                   << " " << fstab->recs[top_idx].fs_type
-                   << " is formattable. Format it.";
+            LERROR << __FUNCTION__ << "(): " << realpath(fstab->recs[top_idx].blk_device)
+                   << " is wiped and " << fstab->recs[top_idx].mount_point << " "
+                   << fstab->recs[top_idx].fs_type << " is formattable. Format it.";
 
             checkpoint_manager.Revert(&fstab->recs[top_idx]);
 
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index bef46e1..57e984d 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -395,6 +395,18 @@
     return false;
 }
 
+void fs_mgr_overlayfs_umount_scratch() {
+    // Lazy umount will allow us to move on and possibly later
+    // establish a new fresh mount without requiring a reboot should
+    // the developer wish to restart.  Old references should melt
+    // away or have no data.  Main goal is to shut the door on the
+    // current overrides with an expectation of a subsequent reboot,
+    // thus any errors here are ignored.
+    umount2(kScratchMountPoint.c_str(), MNT_DETACH);
+    LINFO << "umount(" << kScratchMountPoint << ")";
+    rmdir(kScratchMountPoint.c_str());
+}
+
 // reduce 'DM_DEV_STATUS failed for scratch: No such device or address' noise
 std::string scratch_device_cache;
 
@@ -408,13 +420,7 @@
 
     auto save_errno = errno;
     if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
-        // Lazy umount will allow us to move on and possibly later
-        // establish a new fresh mount without requiring a reboot should
-        // the developer wish to restart.  Old references should melt
-        // away or have no data.  Main goal is to shut the door on the
-        // current overrides with an expectation of a subsequent reboot,
-        // thus any errors here are ignored.
-        umount2(kScratchMountPoint.c_str(), MNT_DETACH);
+        fs_mgr_overlayfs_umount_scratch();
     }
     auto builder = MetadataBuilder::New(super_device, slot_number);
     if (!builder) {
@@ -669,14 +675,26 @@
         }
         changed = true;
     }
-    // Take half of free space, minimum 512MB or free space - 256KB margin.
+    // Take half of free space, minimum 512MB or maximum free - margin.
     static constexpr auto kMinimumSize = uint64_t(512 * 1024 * 1024);
-    static constexpr auto kMarginSize = uint64_t(256 * 1024);
     if (partition->size() < kMinimumSize) {
         auto partition_size =
                 builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
         if ((partition_size > kMinimumSize) || !partition->size()) {
-            partition_size = std::max(std::min(kMinimumSize, partition_size - kMarginSize),
+            // Leave some space for free space jitter of a few erase
+            // blocks, in case they are needed for any individual updates
+            // to any other partition that needs to be flashed while
+            // overlayfs is in force.  Of course if margin_size is not
+            // enough could normally get a flash failure, so
+            // ResizePartition() will delete the scratch partition in
+            // order to fulfill.  Deleting scratch will destroy all of
+            // the adb remount overrides :-( .
+            auto margin_size = uint64_t(3 * 256 * 1024);
+            BlockDeviceInfo info;
+            if (builder->GetBlockDeviceInfo(partition_name, &info)) {
+                margin_size = 3 * info.logical_block_size;
+            }
+            partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
                                       partition_size / 2);
             if (partition_size > partition->size()) {
                 if (!builder->ResizePartition(partition, partition_size)) {
@@ -753,14 +771,20 @@
     return builder->FindPartition(android::base::Basename(kScratchMountPoint)) != nullptr;
 }
 
+bool fs_mgr_overlayfs_invalid(const fstab* fstab) {
+    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
+
+    // in recovery or fastbootd mode, not allowed!
+    if (fs_mgr_access("/system/bin/recovery")) return true;
+
+    return !fstab;
+}
+
 }  // namespace
 
 bool fs_mgr_overlayfs_mount_all(fstab* fstab) {
     auto ret = false;
-
-    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return ret;
-
-    if (!fstab) return ret;
+    if (fs_mgr_overlayfs_invalid(fstab)) return ret;
 
     auto scratch_can_be_mounted = true;
     for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
@@ -773,8 +797,7 @@
                 fs_mgr_overlayfs_mount_scratch(scratch_device,
                                                fs_mgr_overlayfs_scratch_mount_type()) &&
                 !fs_mgr_access(kScratchMountPoint + kOverlayTopDir)) {
-                umount2(kScratchMountPoint.c_str(), MNT_DETACH);
-                rmdir(kScratchMountPoint.c_str());
+                fs_mgr_overlayfs_umount_scratch();
             }
         }
         if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
@@ -790,9 +813,9 @@
 }
 
 std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab) {
-    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return {};
+    if (fs_mgr_overlayfs_invalid(fstab)) return {};
 
-    if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), kScratchMountPoint)) {
+    if (fs_mgr_get_entry_for_mount_point(fstab, kScratchMountPoint)) {
         return {};
     }
 
@@ -867,6 +890,7 @@
     auto ret = true;
     // If scratch exists, but is not mounted, lets gain access to clean
     // specific override entries.
+    auto mount_scratch = false;
     if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
         auto scratch_device = fs_mgr_overlayfs_scratch_device();
         if (scratch_device.empty()) {
@@ -876,7 +900,8 @@
             CreateLogicalPartition(super_device, slot_number, partition_name, true, 0s,
                                    &scratch_device);
         }
-        fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type());
+        mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
+                                                       fs_mgr_overlayfs_scratch_mount_type());
     }
     for (const auto& overlay_mount_point : kOverlayMountPoints) {
         ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change);
@@ -894,6 +919,8 @@
         PERROR << "teardown";
         ret = false;
     }
+    if (mount_scratch) fs_mgr_overlayfs_umount_scratch();
+
     return ret;
 }
 
diff --git a/init/Android.mk b/init/Android.mk
index 69f1d87..0e6ee0b 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -35,7 +35,6 @@
     -Wall -Wextra \
     -Wno-unused-parameter \
     -Werror \
-    -std=gnu++1z \
 
 # --
 
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 8644dae..d35329e 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -413,7 +413,14 @@
     // heads up for instantiating required device(s) for overlayfs logic
     const auto devices = fs_mgr_overlayfs_required_devices(device_tree_fstab_.get());
     for (auto const& device : devices) {
-        InitMappedDevice(device);
+        if (android::base::StartsWith(device, "/dev/block/by-name/")) {
+            required_devices_partition_names_.emplace(basename(device.c_str()));
+            auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); };
+            uevent_listener_.RegenerateUevents(uevent_callback);
+            uevent_listener_.Poll(uevent_callback, 10s);
+        } else {
+            InitMappedDevice(device);
+        }
     }
 
     fs_mgr_overlayfs_mount_all(device_tree_fstab_.get());
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index 8cf2128..d6765b7 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -87,8 +87,8 @@
 }
 
 UeventListener::UeventListener() {
-    // is 2MB enough? udev uses 128MB!
-    device_fd_.reset(uevent_open_socket(2 * 1024 * 1024, true));
+    // is 16MB enough? udev uses 128MB!
+    device_fd_.reset(uevent_open_socket(16 * 1024 * 1024, true));
     if (device_fd_ == -1) {
         LOG(FATAL) << "Could not open uevent socket";
     }
diff --git a/libcutils/uevent.cpp b/libcutils/uevent.cpp
index 2dfceed..721de7c 100644
--- a/libcutils/uevent.cpp
+++ b/libcutils/uevent.cpp
@@ -95,6 +95,8 @@
 int uevent_open_socket(int buf_sz, bool passcred) {
     struct sockaddr_nl addr;
     int on = passcred;
+    int buf_sz_readback = 0;
+    socklen_t optlen = sizeof(buf_sz_readback);
     int s;
 
     memset(&addr, 0, sizeof(addr));
@@ -105,11 +107,21 @@
     s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
     if (s < 0) return -1;
 
-    /* buf_sz should be less than net.core.rmem_max for this to succeed */
-    if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0) {
+    if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0 ||
+          getsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz_readback, &optlen) < 0) {
         close(s);
         return -1;
     }
+    /* Only if SO_RCVBUF was not effective, try SO_RCVBUFFORCE. Generally, we
+     * want to avoid SO_RCVBUFFORCE, because it generates SELinux denials in
+     * case we don't have CAP_NET_ADMIN. This is the case, for example, for
+     * healthd. */
+    if (buf_sz_readback < 2 * buf_sz) {
+        if (setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &buf_sz, sizeof(buf_sz)) < 0) {
+            close(s);
+            return -1;
+        }
+    }
 
     setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
 
diff --git a/property_service/libpropertyinfoparser/Android.bp b/property_service/libpropertyinfoparser/Android.bp
index 70f6faa..6637deb 100644
--- a/property_service/libpropertyinfoparser/Android.bp
+++ b/property_service/libpropertyinfoparser/Android.bp
@@ -12,5 +12,6 @@
         "-Werror",
     ],
     stl: "none",
+    system_shared_libs: [],
     export_include_dirs: ["include"],
 }
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 4576776..d10f7c1 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -5,6 +5,7 @@
     export ANDROID_ASSETS /system/app
     export ANDROID_DATA /data
     export ANDROID_STORAGE /storage
+    export ANDROID_RUNTIME_ROOT /apex/com.android.runtime
     export EXTERNAL_STORAGE /sdcard
     export ASEC_MOUNTPOINT /mnt/asec
     export BOOTCLASSPATH %BOOTCLASSPATH%