[fs-managment] Add support for spawning ram-nand-ctl in an isolated devmgr.
Tests will be converted to use this in future changes. It will allow
tests to be more hermetic.
Tested: runtests -t install-disk-image-test; runtests -t nand-test
Change-Id: I7ddb199ab5325ed7853e8329b5f74b6a00073dc2
diff --git a/system/dev/nand/broker/rules.mk b/system/dev/nand/broker/rules.mk
index 5b3de27..6ef1b3d 100644
--- a/system/dev/nand/broker/rules.mk
+++ b/system/dev/nand/broker/rules.mk
@@ -53,6 +53,8 @@
$(TEST_DIR)/parent.cpp \
MODULE_STATIC_LIBS := \
+ system/ulib/devmgr-integration-test \
+ system/ulib/devmgr-launcher \
system/ulib/fbl \
system/ulib/fzl \
system/ulib/zx \
@@ -85,8 +87,8 @@
$(TEST_DIR)/parent.cpp \
MODULE_STATIC_LIBS := \
- system/ulib/devmgr-integration-test \
- system/ulib/devmgr-launcher \
+ system/ulib/devmgr-integration-test \
+ system/ulib/devmgr-launcher \
system/ulib/fbl \
system/ulib/fzl \
system/ulib/zx \
diff --git a/system/dev/nand/broker/test/parent.h b/system/dev/nand/broker/test/parent.h
index 75ce323..ac8a878 100644
--- a/system/dev/nand/broker/test/parent.h
+++ b/system/dev/nand/broker/test/parent.h
@@ -36,7 +36,7 @@
bool IsBroker() const { return config_.is_broker; }
// Returns a file descriptor for the device.
- int get() const { return ram_nand_ ? ram_nand_->fd() : device_.get(); }
+ int get() { return ram_nand_ ? ram_nand_->fd().get() : device_.get(); }
const zircon_nand_Info& Info() const { return config_.info; }
void SetInfo(const zircon_nand_Info& info);
@@ -48,7 +48,7 @@
uint32_t FirstBlock() const { return config_.first_block; }
private:
- std::unique_ptr<fs_mgmt::RamNand> ram_nand_;
+ std::optional<fs_mgmt::RamNand> ram_nand_;
fbl::unique_fd device_;
TestConfig config_;
fbl::StringBuffer<PATH_MAX> path_;
diff --git a/system/dev/nand/ram-nand/rules.mk b/system/dev/nand/ram-nand/rules.mk
index 1e61496..b8a0347 100644
--- a/system/dev/nand/ram-nand/rules.mk
+++ b/system/dev/nand/ram-nand/rules.mk
@@ -54,6 +54,8 @@
MODULE_STATIC_LIBS := \
system/dev/lib/fake_ddk \
+ system/ulib/devmgr-integration-test \
+ system/ulib/devmgr-launcher \
system/ulib/fbl \
system/ulib/fzl \
system/ulib/ddk \
diff --git a/system/dev/nand/ram-nand/test/ram-nand-ctl.cpp b/system/dev/nand/ram-nand/test/ram-nand-ctl.cpp
index 9264d5e..9dc22a7 100644
--- a/system/dev/nand/ram-nand/test/ram-nand-ctl.cpp
+++ b/system/dev/nand/ram-nand/test/ram-nand-ctl.cpp
@@ -30,7 +30,7 @@
if (fs_mgmt::RamNand::Create(&config, &ram_nand_) == ZX_OK) {
// caller_ want's to own the device, so we re-open it even though
// ram_nand_ already has it open.
- fbl::unique_fd device(dup(ram_nand_->fd()));
+ fbl::unique_fd device(dup(ram_nand_->fd().get()));
caller_.reset(std::move(device));
}
}
@@ -39,11 +39,11 @@
bool IsValid() const { return caller_ ? true : false; }
- const char* path() const { return ram_nand_->path(); }
+ const char* path() { return ram_nand_->path(); }
private:
- std::unique_ptr<fs_mgmt::RamNand> ram_nand_;
+ std::optional<fs_mgmt::RamNand> ram_nand_;
fzl::FdioCaller caller_;
DISALLOW_COPY_ASSIGN_AND_MOVE(NandDevice);
};
diff --git a/system/uapp/disk-pave/rules.mk b/system/uapp/disk-pave/rules.mk
index 36d5623..c4de6db 100644
--- a/system/uapp/disk-pave/rules.mk
+++ b/system/uapp/disk-pave/rules.mk
@@ -76,6 +76,8 @@
system/ulib/block-client \
system/ulib/chromeos-disk-setup \
system/ulib/ddk \
+ system/ulib/devmgr-integration-test \
+ system/ulib/devmgr-launcher \
system/ulib/fbl \
system/ulib/fs-management \
system/ulib/fzl \
diff --git a/system/uapp/disk-pave/test/device-partitioner-test.cpp b/system/uapp/disk-pave/test/device-partitioner-test.cpp
index f81acc9..ccbc4cf 100644
--- a/system/uapp/disk-pave/test/device-partitioner-test.cpp
+++ b/system/uapp/disk-pave/test/device-partitioner-test.cpp
@@ -250,7 +250,7 @@
zircon_nand_RamNandInfo info = kNandInfo;
info.vmo = dup.release();
- std::unique_ptr<fs_mgmt::RamNand> ram_nand;
+ std::optional<fs_mgmt::RamNand> ram_nand;
ASSERT_EQ(fs_mgmt::RamNand::Create(&info, &ram_nand), ZX_OK);
ASSERT_TRUE(InsertTestDevices(ram_nand->path(), true));
device->reset(new SkipBlockDevice(std::move(*ram_nand), std::move(mapper)));
diff --git a/system/uapp/nand-loader/main.cpp b/system/uapp/nand-loader/main.cpp
index 4a9f868..bc3d7ab 100644
--- a/system/uapp/nand-loader/main.cpp
+++ b/system/uapp/nand-loader/main.cpp
@@ -153,7 +153,7 @@
return -1;
}
- std::unique_ptr<fs_mgmt::RamNand> ram_nand;
+ std::optional<fs_mgmt::RamNand> ram_nand;
if (fs_mgmt::RamNand::Create(&ram_nand_config, &ram_nand) != ZX_OK) {
printf("Unable to load device\n");
return -1;
diff --git a/system/uapp/nand-loader/rules.mk b/system/uapp/nand-loader/rules.mk
index fb7569b..beb5857 100644
--- a/system/uapp/nand-loader/rules.mk
+++ b/system/uapp/nand-loader/rules.mk
@@ -13,6 +13,8 @@
$(LOCAL_DIR)/main.cpp \
MODULE_STATIC_LIBS := \
+ system/ulib/devmgr-integration-test \
+ system/ulib/devmgr-launcher \
system/ulib/fbl \
system/ulib/fzl \
system/ulib/zx \
diff --git a/system/ulib/fs-management/include/fs-management/ram-nand.h b/system/ulib/fs-management/include/fs-management/ram-nand.h
index 0bb039a..f80b372 100644
--- a/system/ulib/fs-management/include/fs-management/ram-nand.h
+++ b/system/ulib/fs-management/include/fs-management/ram-nand.h
@@ -5,25 +5,56 @@
#pragma once
#include <memory>
+#include <optional>
#include <inttypes.h>
+#include <fbl/ref_counted.h>
+#include <fbl/ref_ptr.h>
#include <fbl/string.h>
-#include <fbl/string_piece.h>
-#include <fbl/unique_fd.h>
+#include <lib/devmgr-integration-test/fixture.h>
#include <zircon/compiler.h>
#include <zircon/nand/c/fidl.h>
namespace fs_mgmt {
+class RamNand;
+
+class RamNandCtl : public fbl::RefCounted<RamNandCtl> {
+public:
+ // Creates an isolated devmgr and spawns a ram_nand_ctl device in it.
+ static zx_status_t Create(fbl::RefPtr<RamNandCtl>* out);
+
+ ~RamNandCtl() = default;
+
+ const fbl::unique_fd& fd() { return ctl_; }
+ const fbl::unique_fd& devfs_root() { return devmgr_->devfs_root(); }
+
+private:
+ RamNandCtl(fbl::unique_ptr<devmgr_integration_test::IsolatedDevmgr> devmgr,
+ fbl::unique_fd ctl)
+ : devmgr_(std::move(devmgr)), ctl_(std::move(ctl)) {}
+
+ fbl::unique_ptr<devmgr_integration_test::IsolatedDevmgr> devmgr_;
+ fbl::unique_fd ctl_;
+};
+
class RamNand {
public:
- // Creates a ram_nand.
- static zx_status_t Create(const zircon_nand_RamNandInfo* config, std::unique_ptr<RamNand>* out);
+ // Creates a ram_nand under ram_nand_ctl running under the main devmgr.
+ static zx_status_t Create(const zircon_nand_RamNandInfo* config, std::optional<RamNand>* out);
+
+ // Creates a ram_nand device underneath the ram_nand_ctl.
+ static zx_status_t Create(fbl::RefPtr<RamNandCtl> ctl, const zircon_nand_RamNandInfo* config,
+ std::optional<RamNand>* out);
+
+ // Creates a ram_nand_ctl device and then a ram_device underneath.
+ static zx_status_t CreateIsolated(const zircon_nand_RamNandInfo* config,
+ std::optional<RamNand>* out);
// Not copyable.
- RamNand(RamNand&) = delete;
- RamNand& operator=(RamNand&) = delete;
+ RamNand(const RamNand&) = delete;
+ RamNand& operator=(const RamNand&) = delete;
// Movable.
RamNand(RamNand&&) = default;
@@ -34,16 +65,29 @@
// Don't unbind in destructor.
void NoUnbind() { unbind = false; }
- int fd() { return fd_.get(); }
- const char* path() { return path_.c_str(); }
+ const fbl::unique_fd& fd() { return fd_; }
+ const char* path() {
+ if (path_) {
+ return path_->c_str();
+ }
+ return nullptr;
+ }
private:
- RamNand(fbl::StringPiece path, fbl::unique_fd fd)
- : path_(std::move(path)), fd_(std::move(fd)) {}
+ RamNand(fbl::unique_fd fd, fbl::RefPtr<RamNandCtl> ctl)
+ : fd_(std::move(fd)), path_(std::nullopt), parent_(ctl) {}
- fbl::String path_;
+ RamNand(fbl::unique_fd fd, fbl::String path)
+ : fd_(std::move(fd)), path_(path), parent_(nullptr) {}
+
fbl::unique_fd fd_;
bool unbind = true;
+
+ // Only valid if not spawned in an isolated devmgr.
+ std::optional<fbl::String> path_;
+
+ // Optional parent if spawned in an isolated devmgr.
+ fbl::RefPtr<RamNandCtl> parent_;
};
} // namespace fs_mgmt
diff --git a/system/ulib/fs-management/ram-nand.cpp b/system/ulib/fs-management/ram-nand.cpp
index 2c06da1..babff5a 100644
--- a/system/ulib/fs-management/ram-nand.cpp
+++ b/system/ulib/fs-management/ram-nand.cpp
@@ -8,11 +8,12 @@
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
+#include <fbl/auto_call.h>
#include <fbl/string_buffer.h>
#include <fbl/unique_fd.h>
#include <lib/fzl/fdio.h>
+#include <lib/fdio/util.h>
#include <zircon/device/device.h>
#include <zircon/types.h>
#include <zircon/nand/c/fidl.h>
@@ -27,23 +28,53 @@
namespace fs_mgmt {
-zx_status_t RamNand::Create(const zircon_nand_RamNandInfo* config, std::unique_ptr<RamNand>* out) {
+zx_status_t RamNandCtl::Create(fbl::RefPtr<RamNandCtl>* out) {
+ devmgr_launcher::Args args;
+ args.sys_device_driver = devmgr_integration_test::IsolatedDevmgr::kSysdevDriver;
+ args.load_drivers.push_back(devmgr_integration_test::IsolatedDevmgr::kSysdevDriver);
+ args.driver_search_paths.push_back("/boot/driver");
+
+ fbl::unique_ptr<devmgr_integration_test::IsolatedDevmgr> devmgr;
+ zx_status_t st = devmgr_integration_test::IsolatedDevmgr::Create(std::move(args), &devmgr);
+ if (st != ZX_OK) {
+ fprintf(stderr, "Could not create ram_nand_ctl device, %d\n", st);
+ return st;
+ }
+
+ fbl::unique_fd ctl;
+ st = devmgr_integration_test::RecursiveWaitForFile(devmgr->devfs_root(), "misc/nand-ctl",
+ zx::deadline_after(zx::sec(5)), &ctl);
+ if (st != ZX_OK) {
+ fprintf(stderr, "ram_nand_ctl device failed enumerated, %d\n", st);
+ return st;
+ }
+
+ *out = fbl::AdoptRef(new RamNandCtl(std::move(devmgr), std::move(ctl)));
+ return ZX_OK;
+}
+
+zx_status_t RamNand::Create(const zircon_nand_RamNandInfo* config, std::optional<RamNand>* out) {
fbl::unique_fd control(open(kBasePath, O_RDWR));
- fzl::FdioCaller caller(std::move(control));
+
+ zx::channel ctl_svc;
+ zx_status_t st = fdio_get_service_handle(control.release(),
+ ctl_svc.reset_and_get_address());
+
char name[zircon_nand_NAME_LEN + 1];
size_t out_name_size;
zx_status_t status;
- zx_status_t st = zircon_nand_RamNandCtlCreateDevice(caller.borrow_channel(), config, &status,
- name, zircon_nand_NAME_LEN, &out_name_size);
+ st = zircon_nand_RamNandCtlCreateDevice(ctl_svc.get(), config, &status, name,
+ zircon_nand_NAME_LEN, &out_name_size);
if (st != ZX_OK || status != ZX_OK) {
st = st != ZX_OK ? st : status;
fprintf(stderr, "Could not create ram_nand device, %d\n", st);
return st;
}
name[out_name_size] = '\0';
-
fbl::StringBuffer<PATH_MAX> path;
- path.AppendPrintf("%s/%s", kBasePath, name);
+ path.Append(kBasePath);
+ path.Append("/");
+ path.Append(name);
fbl::unique_fd ram_nand(open(path.c_str(), O_RDWR));
if (!ram_nand) {
@@ -51,10 +82,63 @@
return ZX_ERR_INTERNAL;
}
- out->reset(new RamNand(path.ToStringPiece(), std::move(ram_nand)));
+ *out = RamNand(std::move(ram_nand), path.ToString());
return ZX_OK;
}
+zx_status_t RamNand::Create(fbl::RefPtr<RamNandCtl> ctl, const zircon_nand_RamNandInfo* config,
+ std::optional<RamNand>* out) {
+
+ fdio_t* io = fdio_unsafe_fd_to_io(ctl->fd().get());
+ if (io == NULL) {
+ fprintf(stderr, "Could not get fdio object\n");
+ return ZX_ERR_INTERNAL;
+ }
+ zx_handle_t ctl_svc = fdio_unsafe_borrow_channel(io);
+
+ char name[zircon_nand_NAME_LEN + 1];
+ size_t out_name_size;
+ zx_status_t status;
+ zx_status_t st = zircon_nand_RamNandCtlCreateDevice(ctl_svc, config, &status, name,
+ zircon_nand_NAME_LEN, &out_name_size);
+ fdio_unsafe_release(io);
+ if (st != ZX_OK || status != ZX_OK) {
+ st = st != ZX_OK ? st : status;
+ fprintf(stderr, "Could not create ram_nand device, %d\n", st);
+ return st;
+ }
+ name[out_name_size] = '\0';
+
+ // TODO(ZX-3193): We should be able to open relative to ctl->fd(), but
+ // due to a bug, we have to be relative to devfs_root instead.
+ fbl::StringBuffer<PATH_MAX> path;
+ path.Append("misc/nand-ctl/");
+ path.Append(name);
+ fprintf(stderr, "Trying to open (%s)\n", path.c_str());
+
+ // TODO(ZX-3192): We should use RecursiveWaitForFile here but it doesn't seem to
+ // work, so we sleep instead.
+ sleep(1);
+ fbl::unique_fd fd(openat(ctl->devfs_root().get(), path.c_str(), O_RDWR));
+ if (!fd) {
+ fprintf(stderr, "Could not open ram_nand\n");
+ return ZX_ERR_IO;
+ }
+
+ *out = RamNand(std::move(fd), std::move(ctl));
+ return ZX_OK;
+}
+
+zx_status_t RamNand::CreateIsolated(const zircon_nand_RamNandInfo* config,
+ std::optional<RamNand>* out) {
+ fbl::RefPtr<RamNandCtl> ctl;
+ zx_status_t st = RamNandCtl::Create(&ctl);
+ if (st != ZX_OK) {
+ return st;
+ }
+ return Create(std::move(ctl), config, out);
+}
+
RamNand::~RamNand() {
if (unbind && fd_) {
zx_status_t status = static_cast<zx_status_t>(ioctl_device_unbind(fd_.get()));
diff --git a/system/ulib/fs-management/rules.mk b/system/ulib/fs-management/rules.mk
index 23e3db3..2915ec5 100644
--- a/system/ulib/fs-management/rules.mk
+++ b/system/ulib/fs-management/rules.mk
@@ -21,6 +21,8 @@
system/ulib/fbl \
system/ulib/fvm \
system/ulib/fs \
+ system/ulib/devmgr-integration-test \
+ system/ulib/devmgr-launcher \
system/ulib/digest \
system/ulib/ddk \
system/ulib/gpt \