Merge "Open zips using _wopen on windows."
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index f7017dd..ed5f944 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -38,7 +38,6 @@
 #include <android-base/properties.h>
 #include <bootloader_message/bootloader_message.h>
 #include <cutils/android_reboot.h>
-#include <ext4_utils/ext4_utils.h>
 #include <fs_mgr.h>
 #include <fs_mgr_overlayfs.h>
 
@@ -96,27 +95,6 @@
     return result;
 }
 
-static bool fs_has_shared_blocks(const std::string& mount_point, const std::string& device) {
-    std::string path = mount_point + "/lost+found";
-    struct statfs fs;
-    if (statfs(path.c_str(), &fs) == -1 || fs.f_type != EXT4_SUPER_MAGIC) {
-        return false;
-    }
-    unique_fd fd(unix_open(device.c_str(), O_RDONLY));
-    if (fd < 0) {
-        return false;
-    }
-    struct ext4_super_block sb;
-    if (lseek64(fd, 1024, SEEK_SET) < 0 || unix_read(fd, &sb, sizeof(sb)) < 0) {
-        return false;
-    }
-    struct fs_info info;
-    if (ext4_parse_sb(&sb, &info) < 0) {
-        return false;
-    }
-    return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
-}
-
 static bool can_unshare_blocks(int fd, const char* dev) {
     const char* E2FSCK_BIN = "/system/bin/e2fsck";
     if (access(E2FSCK_BIN, X_OK)) {
@@ -250,7 +228,7 @@
     std::set<std::string> dedup;
     for (const auto& partition : partitions) {
         std::string dev = find_mount(partition.c_str(), partition == "/");
-        if (dev.empty() || !fs_has_shared_blocks(partition, dev)) {
+        if (dev.empty() || !fs_mgr_has_shared_blocks(partition, dev)) {
             continue;
         }
         if (can_unshare_blocks(fd.get(), dev.c_str())) {
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index dfb7a6a..e2ea480 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -29,6 +29,7 @@
 #include <regex>
 #include <thread>
 
+#include <android/fdsan.h>
 #include <android/set_abort_message.h>
 
 #include <android-base/file.h>
@@ -801,6 +802,31 @@
   AssertDeath(SIGABRT);
 }
 
+TEST_F(CrasherTest, fdsan_warning_abort_message) {
+  int intercept_result;
+  unique_fd output_fd;
+
+  StartProcess([]() {
+    android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
+    unique_fd fd(open("/dev/null", O_RDONLY | O_CLOEXEC));
+    if (fd == -1) {
+      abort();
+    }
+    close(fd.get());
+    _exit(0);
+  });
+
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(0);
+  FinishIntercept(&intercept_result);
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  ASSERT_MATCH(result, "Abort message: 'attempted to close");
+}
+
 TEST(crash_dump, zombie) {
   pid_t forkpid = fork();
 
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 91e6f71..15557b6 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -457,14 +457,14 @@
     info = nullptr;
   }
 
-  struct siginfo si = {};
+  struct siginfo dummy_info = {};
   if (!info) {
-    memset(&si, 0, sizeof(si));
-    si.si_signo = signal_number;
-    si.si_code = SI_USER;
-    si.si_pid = __getpid();
-    si.si_uid = getuid();
-    info = &si;
+    memset(&dummy_info, 0, sizeof(dummy_info));
+    dummy_info.si_signo = signal_number;
+    dummy_info.si_code = SI_USER;
+    dummy_info.si_pid = __getpid();
+    dummy_info.si_uid = getuid();
+    info = &dummy_info;
   } else if (info->si_code >= 0 || info->si_code == SI_TKILL) {
     // rt_tgsigqueueinfo(2)'s documentation appears to be incorrect on kernels
     // that contain commit 66dd34a (3.9+). The manpage claims to only allow
@@ -473,8 +473,18 @@
   }
 
   void* abort_message = nullptr;
-  if (signal_number != DEBUGGER_SIGNAL && g_callbacks.get_abort_message) {
-    abort_message = g_callbacks.get_abort_message();
+  if (signal_number == DEBUGGER_SIGNAL) {
+    if (info->si_code == SI_QUEUE && info->si_pid == __getpid()) {
+      // Allow for the abort message to be explicitly specified via the sigqueue value.
+      // Keep the bottom bit intact for representing whether we want a backtrace or a tombstone.
+      uintptr_t value = reinterpret_cast<uintptr_t>(info->si_ptr);
+      abort_message = reinterpret_cast<void*>(value & ~1);
+      info->si_ptr = reinterpret_cast<void*>(value & 1);
+    }
+  } else {
+    if (g_callbacks.get_abort_message) {
+      abort_message = g_callbacks.get_abort_message();
+    }
   }
 
   // If sival_int is ~0, it means that the fallback handler has been called
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index 6890643..6a52b12 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -79,12 +79,18 @@
 static std::vector<std::unique_ptr<Action>> action_list;
 static fastboot::FastBootDriver* fb = nullptr;
 
+static constexpr char kStatusFormat[] = "%-50s ";
+
 void fb_init(fastboot::FastBootDriver& fbi) {
     fb = &fbi;
     auto cb = [](std::string& info) { fprintf(stderr, "(bootloader) %s\n", info.c_str()); };
     fb->SetInfoCallback(cb);
 }
 
+void fb_reinit(Transport* transport) {
+    fb->set_transport(transport);
+}
+
 const std::string fb_get_error() {
     return fb->Error();
 }
@@ -332,7 +338,7 @@
     for (auto& a : action_list) {
         a->start = now();
         if (!a->msg.empty()) {
-            fprintf(stderr, "%-50s ", a->msg.c_str());
+            fprintf(stderr, kStatusFormat, a->msg.c_str());
             verbose("\n");
         }
         if (a->op == OP_DOWNLOAD) {
@@ -372,3 +378,20 @@
     action_list.clear();
     return status;
 }
+
+bool fb_reboot_to_userspace() {
+    // First ensure that the queue is flushed.
+    fb_execute_queue();
+
+    fprintf(stderr, kStatusFormat, "Rebooting to userspace fastboot");
+    verbose("\n");
+
+    if (fb->RebootTo("fastboot") != fastboot::RetCode::SUCCESS) {
+        fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
+        return false;
+    }
+    fprintf(stderr, "OKAY\n");
+
+    fb->set_transport(nullptr);
+    return true;
+}
diff --git a/fastboot/engine.h b/fastboot/engine.h
index 8aebdd7..f098ca7 100644
--- a/fastboot/engine.h
+++ b/fastboot/engine.h
@@ -50,6 +50,7 @@
 /* engine.c - high level command queue engine */
 
 void fb_init(fastboot::FastBootDriver& fbi);
+void fb_reinit(Transport* transport);
 
 bool fb_getvar(const std::string& key, std::string* value);
 void fb_queue_flash(const std::string& partition, void* data, uint32_t sz);
@@ -74,6 +75,7 @@
 void fb_queue_resize_partition(const std::string& partition, const std::string& size);
 int64_t fb_execute_queue();
 void fb_set_active(const std::string& slot);
+bool fb_reboot_to_userspace();
 
 /* Current product */
 extern char cur_product[FB_RESPONSE_SZ + 1];
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 4a8ee33..6cf544f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -246,13 +246,8 @@
 // The returned Transport is a singleton, so multiple calls to this function will return the same
 // object, and the caller should not attempt to delete the returned Transport.
 static Transport* open_device() {
-    static Transport* transport = nullptr;
     bool announce = true;
 
-    if (transport != nullptr) {
-        return transport;
-    }
-
     Socket::Protocol protocol = Socket::Protocol::kTcp;
     std::string host;
     int port = 0;
@@ -277,6 +272,7 @@
         }
     }
 
+    Transport* transport = nullptr;
     while (true) {
         if (!host.empty()) {
             std::string error;
@@ -1179,6 +1175,17 @@
     return fb_getvar("is-logical:" + partition, &value) && value == "yes";
 }
 
+static void reboot_to_userspace_fastboot() {
+    if (!fb_reboot_to_userspace()) {
+        die("Must reboot to userspace fastboot to flash logical partitions");
+    }
+
+    // Give the current connection time to close.
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+    fb_reinit(open_device());
+}
+
 static void update_super_partition(bool force_wipe) {
     if (!if_partition_exists("super", "")) {
         return;
@@ -1189,7 +1196,7 @@
     }
 
     if (!is_userspace_fastboot()) {
-        die("Must have userspace fastboot to flash logical partitions");
+        reboot_to_userspace_fastboot();
     }
 
     int fd = open(image.c_str(), O_RDONLY);
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index c508abe..e8587c7 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -52,11 +52,15 @@
 /*************************** PUBLIC *******************************/
 FastBootDriver::FastBootDriver(Transport* transport, std::function<void(std::string&)> info,
                                bool no_checks)
-    : transport(transport) {
+    : transport_(transport) {
     info_cb_ = info;
     disable_checks_ = no_checks;
 }
 
+FastBootDriver::~FastBootDriver() {
+    set_transport(nullptr);
+}
+
 RetCode FastBootDriver::Boot(std::string* response, std::vector<std::string>* info) {
     return RawCommand(Commands::BOOT, response, info);
 }
@@ -93,6 +97,11 @@
     return RawCommand(Commands::REBOOT, response, info);
 }
 
+RetCode FastBootDriver::RebootTo(std::string target, std::string* response,
+                                 std::vector<std::string>* info) {
+    return RawCommand("reboot-" + target, response, info);
+}
+
 RetCode FastBootDriver::SetActive(const std::string& part, std::string* response,
                                   std::vector<std::string>* info) {
     return RawCommand(Commands::SET_ACTIVE + part, response, info);
@@ -332,7 +341,7 @@
 }
 
 RetCode FastBootDriver::WaitForDisconnect() {
-    return transport->WaitForDisconnect() ? IO_ERROR : SUCCESS;
+    return transport_->WaitForDisconnect() ? IO_ERROR : SUCCESS;
 }
 
 /****************************** PROTECTED *************************************/
@@ -344,7 +353,7 @@
         return BAD_ARG;
     }
 
-    if (transport->Write(cmd.c_str(), cmd.size()) != static_cast<int>(cmd.size())) {
+    if (transport_->Write(cmd.c_str(), cmd.size()) != static_cast<int>(cmd.size())) {
         error_ = ErrnoStr("Write to device failed");
         return IO_ERROR;
     }
@@ -378,7 +387,7 @@
     // erase response
     set_response("");
     while ((std::chrono::system_clock::now() - start) < std::chrono::seconds(RESP_TIMEOUT)) {
-        int r = transport->Read(status, FB_RESPONSE_SZ);
+        int r = transport_->Read(status, FB_RESPONSE_SZ);
         if (r < 0) {
             error_ = ErrnoStr("Status read failed");
             return IO_ERROR;
@@ -472,7 +481,7 @@
         return BAD_ARG;
     }
     // Write the buffer
-    ssize_t tmp = transport->Write(buf, size);
+    ssize_t tmp = transport_->Write(buf, size);
 
     if (tmp < 0) {
         error_ = ErrnoStr("Write to device failed in SendBuffer()");
@@ -493,7 +502,7 @@
 
 RetCode FastBootDriver::ReadBuffer(void* buf, size_t size) {
     // Read the buffer
-    ssize_t tmp = transport->Read(buf, size);
+    ssize_t tmp = transport_->Read(buf, size);
 
     if (tmp < 0) {
         error_ = ErrnoStr("Read from device failed in ReadBuffer()");
@@ -539,4 +548,12 @@
     return 0;
 }
 
+void FastBootDriver::set_transport(Transport* transport) {
+    if (transport_) {
+        transport_->Close();
+        delete transport_;
+    }
+    transport_ = transport;
+}
+
 }  // End namespace fastboot
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index 51be3db..a97ed2c 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -66,6 +66,7 @@
     FastBootDriver(Transport* transport,
                    std::function<void(std::string&)> info = [](std::string&) {},
                    bool no_checks = false);
+    ~FastBootDriver();
 
     RetCode Boot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
     RetCode Continue(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
@@ -87,6 +88,8 @@
     RetCode GetVarAll(std::vector<std::string>* response);
     RetCode Powerdown(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
     RetCode Reboot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
+    RetCode RebootTo(std::string target, std::string* response = nullptr,
+                     std::vector<std::string>* info = nullptr);
     RetCode SetActive(const std::string& part, std::string* response = nullptr,
                       std::vector<std::string>* info = nullptr);
     RetCode Upload(const std::string& outfile, std::string* response = nullptr,
@@ -109,6 +112,10 @@
     std::string Error();
     RetCode WaitForDisconnect();
 
+    // Note: changing the transport will close and delete the existing one.
+    void set_transport(Transport* transport);
+    Transport* transport() const { return transport_; }
+
     // This is temporarily public for engine.cpp
     RetCode RawCommand(const std::string& cmd, std::string* response = nullptr,
                        std::vector<std::string>* info = nullptr, int* dsize = nullptr);
@@ -136,7 +143,7 @@
         static const std::string VERIFY;
     };
 
-    Transport* const transport;
+    Transport* transport_;
 
   private:
     RetCode SendBuffer(int fd, size_t size);
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 99f2df8..b0c55e3 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -79,7 +79,8 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
-using DeviceMapper = android::dm::DeviceMapper;
+using android::dm::DeviceMapper;
+using android::dm::DmDeviceState;
 
 // record fs stat
 enum FsStatFlags {
@@ -1400,8 +1401,12 @@
             mount_point = basename(fstab->recs[i].mount_point);
         }
 
-        const char* status = nullptr;
+        if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
+            PERROR << "Could not find verity device for mount point: " << mount_point;
+            continue;
+        }
 
+        const char* status = nullptr;
         std::vector<DeviceMapper::TargetInfo> table;
         if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
             if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index fb57715..531610e 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -141,14 +141,13 @@
 constexpr char upperdir_option[] = "upperdir=";
 
 // default options for mount_point, returns empty string for none available.
-std::string fs_mgr_get_overlayfs_options(const char* mount_point) {
-    auto fsrec_mount_point = std::string(mount_point);
-    auto candidate = fs_mgr_get_overlayfs_candidate(fsrec_mount_point);
+std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) {
+    auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
     if (candidate.empty()) return "";
 
-    auto context = fs_mgr_get_context(fsrec_mount_point);
+    auto context = fs_mgr_get_context(mount_point);
     if (!context.empty()) context = ",rootcontext="s + context;
-    return "override_creds=off,"s + lowerdir_option + fsrec_mount_point + "," + upperdir_option +
+    return "override_creds=off,"s + lowerdir_option + mount_point + "," + upperdir_option +
            candidate + upper_name + ",workdir=" + candidate + work_name + context;
 }
 
@@ -167,10 +166,11 @@
     return true;
 }
 
-std::string fs_mgr_get_overlayfs_options(const fstab* fstab, const char* mount_point) {
-    if (fs_mgr_system_root_image(fstab) && ("/"s == mount_point)) mount_point = "/system";
-
-    return fs_mgr_get_overlayfs_options(mount_point);
+const char* fs_mgr_mount_point(const fstab* fstab, const char* mount_point) {
+    if (!mount_point) return mount_point;
+    if ("/"s != mount_point) return mount_point;
+    if (!fs_mgr_system_root_image(fstab)) return mount_point;
+    return "/system";
 }
 
 // return true if system supports overlayfs
@@ -196,7 +196,7 @@
     if (!fsrec) return false;
 
     auto fsrec_mount_point = fsrec->mount_point;
-    if (!fsrec_mount_point) return false;
+    if (!fsrec_mount_point || !fsrec_mount_point[0]) return false;
     if (!fsrec->blk_device) return false;
 
     if (!fsrec->fs_type) return false;
@@ -309,15 +309,12 @@
     return ret;
 }
 
-bool fs_mgr_overlayfs_mount(const fstab* fstab, const fstab_rec* fsrec) {
-    if (!fs_mgr_wants_overlayfs(fsrec)) return false;
-    auto fsrec_mount_point = fsrec->mount_point;
-    if (!fsrec_mount_point || !fsrec_mount_point[0]) return false;
-    auto options = fs_mgr_get_overlayfs_options(fstab, fsrec_mount_point);
+bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
+    auto options = fs_mgr_get_overlayfs_options(mount_point);
     if (options.empty()) return false;
 
     // hijack __mount() report format to help triage
-    auto report = "__mount(source=overlay,target="s + fsrec_mount_point + ",type=overlay";
+    auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
     const auto opt_list = android::base::Split(options, ",");
     for (const auto opt : opt_list) {
         if (android::base::StartsWith(opt, upperdir_option)) {
@@ -327,7 +324,7 @@
     }
     report = report + ")=";
 
-    auto ret = mount("overlay", fsrec_mount_point, "overlay", MS_RDONLY | MS_RELATIME,
+    auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_RELATIME,
                      options.c_str());
     if (ret) {
         PERROR << report << ret;
@@ -338,8 +335,7 @@
     }
 }
 
-bool fs_mgr_overlayfs_already_mounted(const char* mount_point) {
-    if (!mount_point) return false;
+bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point) {
     std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(
             fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab);
     if (!fstab) return false;
@@ -351,7 +347,7 @@
         if (("overlay"s != fs_type) && ("overlayfs"s != fs_type)) continue;
         auto fsrec_mount_point = fsrec->mount_point;
         if (!fsrec_mount_point) continue;
-        if (strcmp(fsrec_mount_point, mount_point)) continue;
+        if (mount_point != fsrec_mount_point) continue;
         const auto fs_options = fsrec->fs_options;
         if (!fs_options) continue;
         const auto options = android::base::Split(fs_options, ",");
@@ -377,11 +373,10 @@
 
     for (auto i = 0; i < fstab->num_entries; i++) {
         const auto fsrec = &fstab->recs[i];
-        auto fsrec_mount_point = fsrec->mount_point;
-        if (!fsrec_mount_point) continue;
-        if (fs_mgr_overlayfs_already_mounted(fsrec_mount_point)) continue;
-
-        if (fs_mgr_overlayfs_mount(fstab.get(), fsrec)) ret = true;
+        if (!fs_mgr_wants_overlayfs(fsrec)) continue;
+        std::string mount_point(fs_mgr_mount_point(fstab.get(), fsrec->mount_point));
+        if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
+        if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
     }
     return ret;
 }
@@ -405,11 +400,12 @@
     std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
                                                                       fs_mgr_free_fstab);
     std::vector<std::string> mounts;
+    mount_point = fs_mgr_mount_point(fstab.get(), mount_point);
     if (fstab) {
         if (!fs_mgr_get_entry_for_mount_point(fstab.get(), kOverlayMountPoint)) return ret;
         for (auto i = 0; i < fstab->num_entries; i++) {
             const auto fsrec = &fstab->recs[i];
-            auto fsrec_mount_point = fsrec->mount_point;
+            auto fsrec_mount_point = fs_mgr_mount_point(fstab.get(), fsrec->mount_point);
             if (!fsrec_mount_point) continue;
             if (mount_point && strcmp(fsrec_mount_point, mount_point)) continue;
             if (!fs_mgr_wants_overlayfs(fsrec)) continue;
@@ -418,9 +414,6 @@
         if (mounts.empty()) return ret;
     }
 
-    if (mount_point && ("/"s == mount_point) && fs_mgr_system_root_image(fstab.get())) {
-        mount_point = "/system";
-    }
     auto overlay = kOverlayMountPoint + "/overlay/";
     auto save_errno = errno;
     if (!mkdir(overlay.c_str(), 0755)) {
@@ -443,11 +436,10 @@
 // If something is altered, set *change.
 bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
     if (change) *change = false;
-    if (mount_point && ("/"s == mount_point)) {
-        std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(
-                fs_mgr_read_fstab_default(), fs_mgr_free_fstab);
-        if (fs_mgr_system_root_image(fstab.get())) mount_point = "/system";
-    }
+    mount_point = fs_mgr_mount_point(std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)>(
+                                             fs_mgr_read_fstab_default(), fs_mgr_free_fstab)
+                                             .get(),
+                                     mount_point);
     auto ret = true;
     const auto overlay = kOverlayMountPoint + "/overlay";
     const auto oldpath = overlay + (mount_point ?: "");
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 8bcbec2..2b526f6 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -98,9 +98,16 @@
     return nullptr;
 }
 
-DmDeviceState DeviceMapper::state(const std::string& /* name */) const {
-    // TODO(b/110035986): Return the state, as read from the kernel instead
-    return DmDeviceState::INVALID;
+DmDeviceState DeviceMapper::GetState(const std::string& name) const {
+    struct dm_ioctl io;
+    InitIo(&io, name);
+    if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) {
+        return DmDeviceState::INVALID;
+    }
+    if ((io.flags & DM_ACTIVE_PRESENT_FLAG) && !(io.flags & DM_SUSPEND_FLAG)) {
+        return DmDeviceState::ACTIVE;
+    }
+    return DmDeviceState::SUSPENDED;
 }
 
 bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table) {
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 9b61ddc..91f8bb4 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -79,7 +79,7 @@
     // Returns the current state of the underlying device mapper device
     // with given name.
     // One of INVALID, SUSPENDED or ACTIVE.
-    DmDeviceState state(const std::string& name) const;
+    DmDeviceState GetState(const std::string& name) const;
 
     // Creates a device, loads the given table, and activates it. If the device
     // is not able to be activated, it is destroyed, and false is returned.
diff --git a/libsysutils/include/sysutils/OWNERS b/libsysutils/include/sysutils/OWNERS
index b78918e..645baf4 100644
--- a/libsysutils/include/sysutils/OWNERS
+++ b/libsysutils/include/sysutils/OWNERS
@@ -1,2 +1 @@
-per-file Netlink* = ek@google.com
-per-file Netlink* = lorenzo@google.com
+per-file OWNERS,Netlink* = ek@google.com,lorenzo@google.com
diff --git a/libsysutils/src/OWNERS b/libsysutils/src/OWNERS
index b78918e..645baf4 100644
--- a/libsysutils/src/OWNERS
+++ b/libsysutils/src/OWNERS
@@ -1,2 +1 @@
-per-file Netlink* = ek@google.com
-per-file Netlink* = lorenzo@google.com
+per-file OWNERS,Netlink* = ek@google.com,lorenzo@google.com