Merge "ueventd: Put dm-user devices in a folder"
diff --git a/OWNERS b/OWNERS
index 4f8e433..682a067 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,2 +1 @@
enh@google.com
-baligh@google.com
diff --git a/adb/Android.bp b/adb/Android.bp
index 5c1e1fe..c361a14 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -293,8 +293,9 @@
export_include_dirs: ["."],
visibility: [
- "//system/core/adb:__subpackages__",
"//bootable/recovery/minadbd:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
+ "//system/core/adb:__subpackages__",
],
apex_available: [
@@ -499,6 +500,7 @@
],
visibility: [
"//bootable/recovery/minadbd",
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb",
],
}
@@ -578,6 +580,7 @@
"com.android.adbd",
],
visibility: [
+ "//packages/modules/adb",
"//system/core/adb",
],
@@ -636,6 +639,7 @@
visibility: [
"//bootable/recovery/minadbd",
+ "//packages/modules/adb",
"//system/core/adb",
],
}
diff --git a/adb/crypto/Android.bp b/adb/crypto/Android.bp
index e2c27f1..c4052c3 100644
--- a/adb/crypto/Android.bp
+++ b/adb/crypto/Android.bp
@@ -39,8 +39,9 @@
export_include_dirs: ["include"],
visibility: [
- "//system/core/adb:__subpackages__",
"//bootable/recovery/minadbd:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
+ "//system/core/adb:__subpackages__",
],
host_supported: true,
diff --git a/adb/libs/adbconnection/Android.bp b/adb/libs/adbconnection/Android.bp
index f7d2dc1..29ae060 100644
--- a/adb/libs/adbconnection/Android.bp
+++ b/adb/libs/adbconnection/Android.bp
@@ -39,6 +39,7 @@
defaults: ["adbd_defaults"],
visibility: [
"//art:__subpackages__",
+ "//packages/modules/adb/apex:__subpackages__",
"//system/core/adb/apex:__subpackages__",
],
apex_available: [
diff --git a/adb/pairing_auth/Android.bp b/adb/pairing_auth/Android.bp
index a43f4d0..806879d 100644
--- a/adb/pairing_auth/Android.bp
+++ b/adb/pairing_auth/Android.bp
@@ -40,6 +40,7 @@
visibility: [
"//art:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb:__subpackages__",
],
diff --git a/adb/pairing_connection/Android.bp b/adb/pairing_connection/Android.bp
index 9595511..1886885 100644
--- a/adb/pairing_connection/Android.bp
+++ b/adb/pairing_connection/Android.bp
@@ -39,8 +39,9 @@
visibility: [
"//art:__subpackages__",
- "//system/core/adb:__subpackages__",
"//frameworks/base/services:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
+ "//system/core/adb:__subpackages__",
// This needs to be visible to minadbd, even though it's removed via exclude_shared_libs.
"//bootable/recovery/minadbd:__subpackages__",
@@ -129,8 +130,9 @@
visibility: [
"//art:__subpackages__",
- "//system/core/adb:__subpackages__",
"//frameworks/base/services:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
+ "//system/core/adb:__subpackages__",
],
recovery_available: false,
diff --git a/adb/proto/Android.bp b/adb/proto/Android.bp
index 086d10e..ef97208 100644
--- a/adb/proto/Android.bp
+++ b/adb/proto/Android.bp
@@ -40,6 +40,7 @@
},
visibility: [
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb:__subpackages__",
// This needs to be visible to minadbd, even though it's removed via exclude_shared_libs.
@@ -94,6 +95,7 @@
},
visibility: [
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb:__subpackages__",
// This needs to be visible to minadbd, even though it's removed via exclude_shared_libs.
diff --git a/adb/tls/Android.bp b/adb/tls/Android.bp
index e5204f3..1e00548 100644
--- a/adb/tls/Android.bp
+++ b/adb/tls/Android.bp
@@ -40,6 +40,7 @@
visibility: [
"//bootable/recovery/minadbd:__subpackages__",
+ "//packages/modules/adb:__subpackages__",
"//system/core/adb:__subpackages__",
],
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 8788b5a..ef46eb9 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -284,6 +284,7 @@
std::vector<std::string> argv;
argv.push_back(std::to_string(start()));
argv.push_back(std::to_string(size()));
+ argv.push_back(control_device());
return android::base::Join(argv, " ");
}
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 57e3884..478a3c6 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -311,10 +311,15 @@
class DmTargetUser final : public DmTarget {
public:
- DmTargetUser(uint64_t start, uint64_t length) : DmTarget(start, length) {}
+ DmTargetUser(uint64_t start, uint64_t length, std::string control_device)
+ : DmTarget(start, length), control_device_(control_device) {}
std::string name() const override { return "user"; }
+ std::string control_device() const { return control_device_; }
std::string GetParameterString() const override;
+
+ private:
+ std::string control_device_;
};
} // namespace dm
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index ad592e9..b239f31 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -28,6 +28,7 @@
"liblog",
],
static_libs: [
+ "libbrotli",
"libdm",
"libfstab",
"libsnapshot_cow",
@@ -74,6 +75,7 @@
"android/snapshot/snapshot.proto",
"device_info.cpp",
"snapshot.cpp",
+ "snapshot_reader.cpp",
"snapshot_stats.cpp",
"snapshot_stub.cpp",
"snapshot_metadata_updater.cpp",
@@ -108,6 +110,9 @@
defaults: ["libsnapshot_defaults"],
srcs: [":libsnapshot_sources"],
recovery_available: true,
+ cflags: [
+ "-DLIBSNAPSHOT_NO_COW_WRITE",
+ ],
static_libs: [
"libfs_mgr",
],
@@ -121,6 +126,9 @@
],
srcs: [":libsnapshot_sources"],
recovery_available: true,
+ cflags: [
+ "-DLIBSNAPSHOT_NO_COW_WRITE",
+ ],
static_libs: [
"libfs_mgr",
],
@@ -243,6 +251,7 @@
static_libs: [
"android.hardware.boot@1.0",
"android.hardware.boot@1.1",
+ "libbrotli",
"libfs_mgr",
"libgsi",
"libgmock",
@@ -275,9 +284,11 @@
"snapshotctl.cpp",
],
static_libs: [
+ "libbrotli",
"libfstab",
"libsnapshot",
"libsnapshot_cow",
+ "libz",
"update_metadata-protos",
],
shared_libs: [
@@ -331,6 +342,7 @@
],
static_libs: [
"libbase",
+ "libbrotli",
"libcrypto_static",
"libcutils",
"libext2_uuid",
@@ -344,6 +356,7 @@
"libsnapshot_cow",
"libsnapshot_test_helpers",
"libprotobuf-mutator",
+ "libz",
],
header_libs: [
"libchrome",
@@ -544,9 +557,11 @@
"libsnapshot_snapuserd",
"libcutils_sockets",
"libz",
+ "libdm",
],
header_libs: [
"libstorage_literals_headers",
+ "libfiemap_headers",
],
test_min_api_level: 30,
auto_gen_config: true,
diff --git a/fs_mgr/libsnapshot/cow_snapuserd_test.cpp b/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
index 75e54f7..1d6c104 100644
--- a/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <fcntl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <chrono>
#include <iostream>
#include <memory>
#include <string_view>
@@ -25,6 +25,7 @@
#include <android-base/file.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
+#include <libdm/loop_control.h>
#include <libsnapshot/cow_writer.h>
#include <libsnapshot/snapuserd_client.h>
#include <storage_literals/storage_literals.h>
@@ -34,6 +35,8 @@
using namespace android::storage_literals;
using android::base::unique_fd;
+using LoopDevice = android::dm::LoopDevice;
+using namespace std::chrono_literals;
class SnapuserdTest : public ::testing::Test {
protected:
@@ -50,6 +53,18 @@
cow_product_1_ = std::make_unique<TemporaryFile>();
ASSERT_GE(cow_product_1_->fd, 0) << strerror(errno);
+ // Create temp files in the PWD as selinux
+ // allows kernel domin to read from that directory only
+ // on userdebug/eng builds. Creating files under /data/local/tmp
+ // will have selinux denials.
+ std::string path = android::base::GetExecutableDirectory();
+
+ system_a_ = std::make_unique<TemporaryFile>(path);
+ ASSERT_GE(system_a_->fd, 0) << strerror(errno);
+
+ product_a_ = std::make_unique<TemporaryFile>(path);
+ ASSERT_GE(product_a_->fd, 0) << strerror(errno);
+
size_ = 100_MiB;
}
@@ -61,6 +76,12 @@
cow_product_1_ = nullptr;
}
+ std::unique_ptr<TemporaryFile> system_a_;
+ std::unique_ptr<TemporaryFile> product_a_;
+
+ std::unique_ptr<LoopDevice> system_a_loop_;
+ std::unique_ptr<LoopDevice> product_a_loop_;
+
std::unique_ptr<TemporaryFile> cow_system_;
std::unique_ptr<TemporaryFile> cow_product_;
@@ -76,6 +97,9 @@
std::string system_device_name_;
std::string product_device_name_;
+ std::string system_device_ctrl_name_;
+ std::string product_device_ctrl_name_;
+
std::unique_ptr<uint8_t[]> random_buffer_1_;
std::unique_ptr<uint8_t[]> random_buffer_2_;
std::unique_ptr<uint8_t[]> zero_buffer_;
@@ -86,10 +110,18 @@
void CreateCowDevice(std::unique_ptr<TemporaryFile>& cow);
void CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow);
void CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow);
+ void DeleteDmUser(std::unique_ptr<TemporaryFile>& cow, std::string snapshot_device);
void StartSnapuserdDaemon();
void CreateSnapshotDevices();
void SwitchSnapshotDevices();
+ std::string GetSystemControlPath() {
+ return std::string("/dev/dm-user-") + system_device_ctrl_name_;
+ }
+ std::string GetProductControlPath() {
+ return std::string("/dev/dm-user-") + product_device_ctrl_name_;
+ }
+
void TestIO(unique_fd& snapshot_fd, std::unique_ptr<uint8_t[]>& buffer);
SnapuserdClient client_;
};
@@ -97,6 +129,7 @@
void SnapuserdTest::Init() {
unique_fd rnd_fd;
loff_t offset = 0;
+ std::unique_ptr<uint8_t[]> random_buffer = std::make_unique<uint8_t[]>(1_MiB);
rnd_fd.reset(open("/dev/random", O_RDONLY));
ASSERT_TRUE(rnd_fd > 0);
@@ -118,10 +151,27 @@
offset += 1_MiB;
}
- sys_fd_.reset(open("/dev/block/mapper/system_a", O_RDONLY));
+ for (size_t j = 0; j < (800_MiB / 1_MiB); j++) {
+ ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer.get(), 1_MiB, 0), true);
+ ASSERT_EQ(android::base::WriteFully(system_a_->fd, random_buffer.get(), 1_MiB), true);
+ }
+
+ for (size_t j = 0; j < (800_MiB / 1_MiB); j++) {
+ ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer.get(), 1_MiB, 0), true);
+ ASSERT_EQ(android::base::WriteFully(product_a_->fd, random_buffer.get(), 1_MiB), true);
+ }
+
+ // Create loopback devices
+ system_a_loop_ = std::make_unique<LoopDevice>(std::string(system_a_->path), 10s);
+ ASSERT_TRUE(system_a_loop_->valid());
+
+ product_a_loop_ = std::make_unique<LoopDevice>(std::string(product_a_->path), 10s);
+ ASSERT_TRUE(product_a_loop_->valid());
+
+ sys_fd_.reset(open(system_a_loop_->device().c_str(), O_RDONLY));
ASSERT_TRUE(sys_fd_ > 0);
- product_fd_.reset(open("/dev/block/mapper/product_a", O_RDONLY));
+ product_fd_.reset(open(product_a_loop_->device().c_str(), O_RDONLY));
ASSERT_TRUE(product_fd_ > 0);
// Read from system partition from offset 0 of size 100MB
@@ -183,47 +233,65 @@
}
void SnapuserdTest::CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow) {
- unique_fd system_a_fd;
std::string cmd;
system_device_name_.clear();
+ system_device_ctrl_name_.clear();
// Create a COW device. Number of sectors is chosen random which can
// hold at least 400MB of data
- system_a_fd.reset(open("/dev/block/mapper/system_a", O_RDONLY));
- ASSERT_TRUE(system_a_fd > 0);
-
- int err = ioctl(system_a_fd.get(), BLKGETSIZE, &system_blksize_);
+ int err = ioctl(sys_fd_.get(), BLKGETSIZE, &system_blksize_);
ASSERT_GE(err, 0);
std::string str(cow->path);
std::size_t found = str.find_last_of("/\\");
ASSERT_NE(found, std::string::npos);
system_device_name_ = str.substr(found + 1);
+
+ // Create a control device
+ system_device_ctrl_name_ = system_device_name_ + "-ctrl";
cmd = "dmctl create " + system_device_name_ + " user 0 " + std::to_string(system_blksize_);
+ cmd += " " + system_device_ctrl_name_;
+
+ system(cmd.c_str());
+}
+
+void SnapuserdTest::DeleteDmUser(std::unique_ptr<TemporaryFile>& cow, std::string snapshot_device) {
+ std::string cmd;
+
+ cmd = "dmctl delete " + snapshot_device;
+ system(cmd.c_str());
+
+ cmd.clear();
+
+ std::string str(cow->path);
+ std::size_t found = str.find_last_of("/\\");
+ ASSERT_NE(found, std::string::npos);
+ std::string device_name = str.substr(found + 1);
+
+ cmd = "dmctl delete " + device_name;
system(cmd.c_str());
}
void SnapuserdTest::CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow) {
- unique_fd product_a_fd;
std::string cmd;
product_device_name_.clear();
+ product_device_ctrl_name_.clear();
// Create a COW device. Number of sectors is chosen random which can
// hold at least 400MB of data
- product_a_fd.reset(open("/dev/block/mapper/product_a", O_RDONLY));
- ASSERT_TRUE(product_a_fd > 0);
-
- int err = ioctl(product_a_fd.get(), BLKGETSIZE, &product_blksize_);
+ int err = ioctl(product_fd_.get(), BLKGETSIZE, &product_blksize_);
ASSERT_GE(err, 0);
std::string str(cow->path);
std::size_t found = str.find_last_of("/\\");
ASSERT_NE(found, std::string::npos);
product_device_name_ = str.substr(found + 1);
+ product_device_ctrl_name_ = product_device_name_ + "-ctrl";
cmd = "dmctl create " + product_device_name_ + " user 0 " + std::to_string(product_blksize_);
+ cmd += " " + product_device_ctrl_name_;
system(cmd.c_str());
}
@@ -234,10 +302,12 @@
ret = client_.StartSnapuserd();
ASSERT_EQ(ret, 0);
- ret = client_.InitializeSnapuserd(cow_system_->path, "/dev/block/mapper/system_a");
+ ret = client_.InitializeSnapuserd(cow_system_->path, system_a_loop_->device(),
+ GetSystemControlPath());
ASSERT_EQ(ret, 0);
- ret = client_.InitializeSnapuserd(cow_product_->path, "/dev/block/mapper/product_a");
+ ret = client_.InitializeSnapuserd(cow_product_->path, product_a_loop_->device(),
+ GetProductControlPath());
ASSERT_EQ(ret, 0);
}
@@ -245,7 +315,7 @@
std::string cmd;
cmd = "dmctl create system-snapshot -ro snapshot 0 " + std::to_string(system_blksize_);
- cmd += " /dev/block/mapper/system_a";
+ cmd += " " + system_a_loop_->device();
cmd += " /dev/block/mapper/" + system_device_name_;
cmd += " P 8";
@@ -254,7 +324,7 @@
cmd.clear();
cmd = "dmctl create product-snapshot -ro snapshot 0 " + std::to_string(product_blksize_);
- cmd += " /dev/block/mapper/product_a";
+ cmd += " " + product_a_loop_->device();
cmd += " /dev/block/mapper/" + product_device_name_;
cmd += " P 8";
@@ -265,7 +335,7 @@
std::string cmd;
cmd = "dmctl create system-snapshot-1 -ro snapshot 0 " + std::to_string(system_blksize_);
- cmd += " /dev/block/mapper/system_a";
+ cmd += " " + system_a_loop_->device();
cmd += " /dev/block/mapper/" + system_device_name_;
cmd += " P 8";
@@ -274,7 +344,7 @@
cmd.clear();
cmd = "dmctl create product-snapshot-1 -ro snapshot 0 " + std::to_string(product_blksize_);
- cmd += " /dev/block/mapper/product_a";
+ cmd += " " + product_a_loop_->device();
cmd += " /dev/block/mapper/" + product_device_name_;
cmd += " P 8";
@@ -318,7 +388,7 @@
//
// IO path:
//
- // dm-snap->dm-snap-persistent->dm-user->snapuserd->read_from_system_a_partition
+ // dm-snap->dm-snap-persistent->dm-user->snapuserd->read_from_(system_a/product_a) partition
// (copy op) -> return
ASSERT_EQ(ReadFullyAtOffset(snapshot_fd, snapuserd_buffer.get(), size_, offset), true);
@@ -379,24 +449,33 @@
ASSERT_TRUE(snapshot_fd > 0);
TestIO(snapshot_fd, product_buffer_);
+ snapshot_fd.reset(-1);
+
// Sequence of operations for transition
CreateCowDevice(cow_system_1_);
CreateCowDevice(cow_product_1_);
+ // Create dm-user which creates new control devices
CreateSystemDmUser(cow_system_1_);
CreateProductDmUser(cow_product_1_);
- std::vector<std::pair<std::string, std::string>> vec;
- vec.push_back(std::make_pair(cow_system_1_->path, "/dev/block/mapper/system_a"));
- vec.push_back(std::make_pair(cow_product_1_->path, "/dev/block/mapper/product_a"));
+ // Send the path information to second stage daemon through vector
+ std::vector<std::vector<std::string>> vec{
+ {cow_system_1_->path, system_a_loop_->device(), GetSystemControlPath()},
+ {cow_product_1_->path, product_a_loop_->device(), GetProductControlPath()}};
- // Start the second stage deamon and send the devices
+ // Start the second stage deamon and send the devices information through
+ // vector.
ASSERT_EQ(client_.RestartSnapuserd(vec), 0);
// TODO: This is not switching snapshot device but creates a new table;
- // however, it should serve the testing purpose.
+ // Second stage daemon will be ready to serve the IO request. From now
+ // onwards, we can go ahead and shutdown the first stage daemon
SwitchSnapshotDevices();
+ DeleteDmUser(cow_system_, "system-snapshot");
+ DeleteDmUser(cow_product_, "product-snapshot");
+
// Stop the first stage daemon
ASSERT_EQ(client_.StopSnapuserd(true), 0);
@@ -409,6 +488,11 @@
ASSERT_TRUE(snapshot_fd > 0);
TestIO(snapshot_fd, product_buffer_);
+ snapshot_fd.reset(-1);
+
+ DeleteDmUser(cow_system_1_, "system-snapshot-1");
+ DeleteDmUser(cow_product_1_, "product-snapshot-1");
+
// Stop the second stage daemon
ASSERT_EQ(client_.StopSnapuserd(false), 0);
}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 1bc972e..403e350 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -532,8 +532,8 @@
// Target/base device (eg system_b), always present.
std::string target_device;
- // COW path (eg system_cow). Not present if no COW is needed.
- std::string cow_device;
+ // COW name (eg system_cow). Not present if no COW is needed.
+ std::string cow_device_name;
// dm-snapshot instance. Not present in Update mode for VABC.
std::string snapshot_device;
@@ -626,6 +626,9 @@
bool GetMappedImageDeviceStringOrPath(const std::string& device_name,
std::string* device_string_or_mapped_path);
+ // Same as above, but for paths only (no major:minor device strings).
+ bool GetMappedImageDevicePath(const std::string& device_name, std::string* device_path);
+
std::string gsid_dir_;
std::string metadata_dir_;
std::unique_ptr<IDeviceInfo> device_;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
index bf57a00..da058f9 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
@@ -42,6 +42,29 @@
android::base::unique_fd source_fd_;
};
+// Send writes to a COW or a raw device directly, based on a threshold.
+class CompressedSnapshotWriter : public ISnapshotWriter {
+ public:
+ CompressedSnapshotWriter(const CowOptions& options);
+
+ // Sets the COW device, if needed.
+ bool SetCowDevice(android::base::unique_fd&& cow_device);
+
+ bool Flush() override;
+ uint64_t GetCowSize() override;
+ std::unique_ptr<FileDescriptor> OpenReader() override;
+
+ protected:
+ bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
+ bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
+ bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
+
+ private:
+ android::base::unique_fd cow_device_;
+
+ std::unique_ptr<CowWriter> cow_;
+};
+
// Write directly to a dm-snapshot device.
class OnlineKernelSnapshotWriter : public ISnapshotWriter {
public:
@@ -52,7 +75,7 @@
bool Flush() override;
uint64_t GetCowSize() override { return cow_size_; }
- virtual std::unique_ptr<FileDescriptor> OpenReader() override;
+ std::unique_ptr<FileDescriptor> OpenReader() override;
protected:
bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h
index d495014..2f727d6 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h
@@ -60,9 +60,11 @@
class Snapuserd final {
public:
- Snapuserd(const std::string& in_cow_device, const std::string& in_backing_store_device)
+ Snapuserd(const std::string& in_cow_device, const std::string& in_backing_store_device,
+ const std::string& in_control_device)
: cow_device_(in_cow_device),
backing_store_device_(in_backing_store_device),
+ control_device_(in_control_device),
metadata_read_done_(false) {}
bool Init();
@@ -75,6 +77,8 @@
int ReadDiskExceptions(chunk_t chunk, size_t size);
int ReadData(chunk_t chunk, size_t size);
+ std::string GetControlDevicePath() { return control_device_; }
+
private:
int ProcessReplaceOp(const CowOperation* cow_op);
int ProcessCopyOp(const CowOperation* cow_op);
@@ -82,6 +86,7 @@
std::string cow_device_;
std::string backing_store_device_;
+ std::string control_device_;
unique_fd cow_fd_;
unique_fd backing_store_fd_;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
index 535e923..ab2149e 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h
@@ -51,8 +51,9 @@
public:
int StartSnapuserd();
int StopSnapuserd(bool firstStageDaemon);
- int RestartSnapuserd(std::vector<std::pair<std::string, std::string>>& vec);
- int InitializeSnapuserd(std::string cow_device, std::string backing_device);
+ int RestartSnapuserd(std::vector<std::vector<std::string>>& vec);
+ int InitializeSnapuserd(std::string cow_device, std::string backing_device,
+ std::string control_device);
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_kernel.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_kernel.h
index 1a6ba8f..1037c12 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_kernel.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_kernel.h
@@ -80,7 +80,6 @@
__u64 flags;
__u64 sector;
__u64 len;
- __u64 io_in_progress;
} __attribute__((packed));
struct dm_user_payload {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
index 584fe71..a1ebd3a 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h
@@ -60,7 +60,8 @@
virtual ~Stoppable() {}
- virtual void ThreadStart(std::string cow_device, std::string backing_device) = 0;
+ virtual void ThreadStart(std::string cow_device, std::string backing_device,
+ std::string control_device) = 0;
bool StopRequested() {
// checks if value in future object is available
@@ -78,7 +79,8 @@
bool terminating_;
std::vector<std::unique_ptr<Client>> clients_vec_;
- void ThreadStart(std::string cow_device, std::string backing_device) override;
+ void ThreadStart(std::string cow_device, std::string backing_device,
+ std::string control_device) override;
void ShutdownThreads();
DaemonOperations Resolveop(std::string& input);
std::string GetDaemonStatus();
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 2df2c94..3541ef6 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -44,6 +44,7 @@
#include "device_info.h"
#include "partition_cow_creator.h"
#include "snapshot_metadata_updater.h"
+#include "snapshot_reader.h"
#include "utility.h"
namespace android {
@@ -270,7 +271,7 @@
return false;
}
- if (!EnsureNoOverflowSnapshot(lock.get())) {
+ if (!IsCompressionEnabled() && !EnsureNoOverflowSnapshot(lock.get())) {
LOG(ERROR) << "Cannot ensure there are no overflow snapshots.";
return false;
}
@@ -1715,7 +1716,7 @@
return false;
}
if (paths) {
- paths->cow_device = cow_device;
+ paths->cow_device_name = cow_name;
}
remaining_time = GetRemainingTime(params.timeout_ms, begin);
@@ -1723,6 +1724,7 @@
if (context == SnapshotContext::Update && IsCompressionEnabled()) {
// Stop here, we can't run dm-user yet, the COW isn't built.
+ created_devices.Release();
return true;
}
@@ -2470,6 +2472,12 @@
std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter(
const android::fs_mgr::CreateLogicalPartitionParams& params) {
+#if defined(LIBSNAPSHOT_NO_COW_WRITE)
+ (void)params;
+
+ LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery";
+ return nullptr;
+#else
// First unmap any existing mapping.
auto lock = LockShared();
if (!lock) return nullptr;
@@ -2485,7 +2493,7 @@
}
SnapshotStatus status;
- if (!paths.cow_device.empty()) {
+ if (!paths.cow_device_name.empty()) {
if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) {
return nullptr;
}
@@ -2503,12 +2511,49 @@
return OpenCompressedSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths);
}
return OpenKernelSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths);
+#endif
}
+#if !defined(LIBSNAPSHOT_NO_COW_WRITE)
std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenCompressedSnapshotWriter(
- LockedFile*, const std::string&, const SnapshotStatus&, const SnapshotPaths&) {
- LOG(ERROR) << "OpenSnapshotWriter not yet implemented for compression";
- return nullptr;
+ LockedFile* lock, [[maybe_unused]] const std::string& partition_name,
+ const SnapshotStatus& status, const SnapshotPaths& paths) {
+ CHECK(lock);
+
+ CowOptions cow_options;
+ cow_options.compression = "gz";
+ cow_options.max_blocks = {status.device_size() / cow_options.block_size};
+
+ // Currently we don't support partial snapshots, since partition_cow_creator
+ // never creates this scenario.
+ CHECK(status.snapshot_size() == status.device_size());
+
+ auto writer = std::make_unique<CompressedSnapshotWriter>(cow_options);
+
+ unique_fd base_fd(open(paths.target_device.c_str(), O_RDWR | O_CLOEXEC));
+ if (base_fd < 0) {
+ PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << paths.target_device;
+ return nullptr;
+ }
+ writer->SetSourceDevice(std::move(base_fd));
+
+ std::string cow_path;
+ if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) {
+ LOG(ERROR) << "Could not determine path for " << paths.cow_device_name;
+ return nullptr;
+ }
+
+ unique_fd cow_fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC));
+ if (cow_fd < 0) {
+ PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << cow_path;
+ return nullptr;
+ }
+ if (!writer->SetCowDevice(std::move(cow_fd))) {
+ LOG(ERROR) << "Could not create COW writer from " << cow_path;
+ return nullptr;
+ }
+
+ return writer;
}
std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenKernelSnapshotWriter(
@@ -2533,6 +2578,7 @@
return writer;
}
+#endif // !defined(LIBSNAPSHOT_NO_COW_WRITE)
bool SnapshotManager::UnmapUpdateSnapshot(const std::string& target_partition_name) {
auto lock = LockShared();
@@ -2871,6 +2917,22 @@
return SnapshotMergeStats::GetInstance(*this);
}
+// This is only to be used in recovery or normal Android (not first-stage init).
+// We don't guarantee dm paths are available in first-stage init, because ueventd
+// isn't running yet.
+bool SnapshotManager::GetMappedImageDevicePath(const std::string& device_name,
+ std::string* device_path) {
+ auto& dm = DeviceMapper::Instance();
+
+ // Try getting the device string if it is a device mapper device.
+ if (dm.GetState(device_name) != DmDeviceState::INVALID) {
+ return dm.GetDmDevicePathByName(device_name, device_path);
+ }
+
+ // Otherwise, get path from IImageManager.
+ return images_->GetMappedImageDevice(device_name, device_path);
+}
+
bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device_name,
std::string* device_string_or_mapped_path) {
auto& dm = DeviceMapper::Instance();
diff --git a/fs_mgr/libsnapshot/snapshot_reader.cpp b/fs_mgr/libsnapshot/snapshot_reader.cpp
new file mode 100644
index 0000000..0d47468
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_reader.cpp
@@ -0,0 +1,77 @@
+//
+// Copyright (C) 2020 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 <ext4_utils/ext4_utils.h>
+
+#include "snapshot_reader.h"
+
+namespace android {
+namespace snapshot {
+
+// Not supported.
+bool ReadOnlyFileDescriptor::Open(const char*, int, mode_t) {
+ errno = EINVAL;
+ return false;
+}
+
+bool ReadOnlyFileDescriptor::Open(const char*, int) {
+ errno = EINVAL;
+ return false;
+}
+
+ssize_t ReadOnlyFileDescriptor::Write(const void*, size_t) {
+ errno = EINVAL;
+ return false;
+}
+
+bool ReadOnlyFileDescriptor::BlkIoctl(int, uint64_t, uint64_t, int*) {
+ errno = EINVAL;
+ return false;
+}
+
+ReadFdFileDescriptor::ReadFdFileDescriptor(android::base::unique_fd&& fd) : fd_(std::move(fd)) {}
+
+ssize_t ReadFdFileDescriptor::Read(void* buf, size_t count) {
+ return read(fd_.get(), buf, count);
+}
+
+off64_t ReadFdFileDescriptor::Seek(off64_t offset, int whence) {
+ return lseek(fd_.get(), offset, whence);
+}
+
+uint64_t ReadFdFileDescriptor::BlockDevSize() {
+ return get_block_device_size(fd_.get());
+}
+
+bool ReadFdFileDescriptor::Close() {
+ fd_ = {};
+ return true;
+}
+
+bool ReadFdFileDescriptor::IsSettingErrno() {
+ return true;
+}
+
+bool ReadFdFileDescriptor::IsOpen() {
+ return fd_ >= 0;
+}
+
+bool ReadFdFileDescriptor::Flush() {
+ return true;
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_reader.h b/fs_mgr/libsnapshot/snapshot_reader.h
new file mode 100644
index 0000000..1f2ffe2
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_reader.h
@@ -0,0 +1,50 @@
+//
+// Copyright (C) 2020 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.
+//
+
+#pragma once
+
+#include <android-base/file.h>
+#include <payload_consumer/file_descriptor.h>
+
+namespace android {
+namespace snapshot {
+
+class ReadOnlyFileDescriptor : public chromeos_update_engine::FileDescriptor {
+ public:
+ bool Open(const char* path, int flags, mode_t mode) override;
+ bool Open(const char* path, int flags) override;
+ ssize_t Write(const void* buf, size_t count) override;
+ bool BlkIoctl(int request, uint64_t start, uint64_t length, int* result) override;
+};
+
+class ReadFdFileDescriptor : public ReadOnlyFileDescriptor {
+ public:
+ explicit ReadFdFileDescriptor(android::base::unique_fd&& fd);
+
+ ssize_t Read(void* buf, size_t count) override;
+ off64_t Seek(off64_t offset, int whence) override;
+ uint64_t BlockDevSize() override;
+ bool Close() override;
+ bool IsSettingErrno() override;
+ bool IsOpen() override;
+ bool Flush() override;
+
+ private:
+ android::base::unique_fd fd_;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp
index 1958f18..aa49ab1 100644
--- a/fs_mgr/libsnapshot/snapshot_writer.cpp
+++ b/fs_mgr/libsnapshot/snapshot_writer.cpp
@@ -19,10 +19,12 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <payload_consumer/file_descriptor.h>
+#include "snapshot_reader.h"
namespace android {
namespace snapshot {
+using android::base::unique_fd;
using chromeos_update_engine::FileDescriptor;
ISnapshotWriter::ISnapshotWriter(const CowOptions& options) : ICowWriter(options) {}
@@ -31,6 +33,40 @@
source_fd_ = std::move(source_fd);
}
+CompressedSnapshotWriter::CompressedSnapshotWriter(const CowOptions& options)
+ : ISnapshotWriter(options) {}
+
+bool CompressedSnapshotWriter::SetCowDevice(android::base::unique_fd&& cow_device) {
+ cow_device_ = std::move(cow_device);
+ cow_ = std::make_unique<CowWriter>(options_);
+
+ return cow_->Initialize(cow_device_);
+}
+bool CompressedSnapshotWriter::Flush() {
+ return cow_->Flush();
+}
+
+uint64_t CompressedSnapshotWriter::GetCowSize() {
+ return cow_->GetCowSize();
+}
+
+std::unique_ptr<FileDescriptor> CompressedSnapshotWriter::OpenReader() {
+ return nullptr;
+}
+
+bool CompressedSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) {
+ return cow_->AddCopy(new_block, old_block);
+}
+
+bool CompressedSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data,
+ size_t size) {
+ return cow_->AddRawBlocks(new_block_start, data, size);
+}
+
+bool CompressedSnapshotWriter::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
+ return cow_->AddZeroBlocks(new_block_start, num_blocks);
+}
+
OnlineKernelSnapshotWriter::OnlineKernelSnapshotWriter(const CowOptions& options)
: ISnapshotWriter(options) {}
@@ -83,8 +119,12 @@
}
std::unique_ptr<FileDescriptor> OnlineKernelSnapshotWriter::OpenReader() {
- LOG(ERROR) << "OnlineKernelSnapshotWriter::OpenReader not yet implemented";
- return nullptr;
+ unique_fd fd(dup(snapshot_fd_.get()));
+ if (fd < 0) {
+ PLOG(ERROR) << "dup2 failed in OpenReader";
+ return nullptr;
+ }
+ return std::make_unique<ReadFdFileDescriptor>(std::move(fd));
}
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
index 3ed853f..62ef1b0 100644
--- a/fs_mgr/libsnapshot/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -34,18 +34,6 @@
static_assert(PAYLOAD_SIZE >= BLOCK_SIZE);
-class Target {
- public:
- // Represents an already-created Target, which is referenced by UUID.
- Target(std::string uuid) : uuid_(uuid) {}
-
- const auto& uuid() { return uuid_; }
- std::string control_path() { return std::string("/dev/dm-user-") + uuid(); }
-
- private:
- const std::string uuid_;
-};
-
void BufferSink::Initialize(size_t size) {
buffer_size_ = size;
buffer_offset_ = 0;
@@ -498,26 +486,13 @@
return false;
}
- std::string str(cow_device_);
- std::size_t found = str.find_last_of("/\\");
- CHECK(found != std::string::npos);
- std::string device_name = str.substr(found + 1);
+ std::string control_path = GetControlDevicePath();
- LOG(DEBUG) << "Fetching UUID for: " << device_name;
+ LOG(DEBUG) << "Opening control device " << control_path;
- auto& dm = dm::DeviceMapper::Instance();
- std::string uuid;
- if (!dm.GetDmDeviceUuidByName(device_name, &uuid)) {
- LOG(ERROR) << "Unable to find UUID for " << cow_device_;
- return false;
- }
-
- LOG(DEBUG) << "UUID: " << uuid;
- Target t(uuid);
-
- ctrl_fd_.reset(open(t.control_path().c_str(), O_RDWR));
+ ctrl_fd_.reset(open(control_path.c_str(), O_RDWR));
if (ctrl_fd_ < 0) {
- LOG(ERROR) << "Unable to open " << t.control_path();
+ LOG(ERROR) << "Unable to open " << control_path;
return false;
}
@@ -553,7 +528,6 @@
case DM_USER_MAP_READ: {
size_t remaining_size = header->len;
loff_t offset = 0;
- header->io_in_progress = 0;
ret = 0;
do {
size_t read_size = std::min(PAYLOAD_SIZE, remaining_size);
@@ -619,7 +593,6 @@
if (remaining_size) {
LOG(DEBUG) << "Write done ret: " << ret
<< " remaining size: " << remaining_size;
- bufsink_.GetHeaderPtr()->io_in_progress = 1;
}
} while (remaining_size);
diff --git a/fs_mgr/libsnapshot/snapuserd_client.cpp b/fs_mgr/libsnapshot/snapuserd_client.cpp
index bef8f5c..78dbada 100644
--- a/fs_mgr/libsnapshot/snapuserd_client.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_client.cpp
@@ -127,24 +127,6 @@
return msgStr;
}
-#if 0
-std::string SnapuserdClient::Receivemsg() {
- char msg[PACKET_SIZE];
- std::string msgStr("fail");
- int ret;
-
- ret = TEMP_FAILURE_RETRY(recv(sockfd_, msg, PACKET_SIZE, 0));
- if (ret <= 0) {
- LOG(ERROR) << "recv failed " << strerror(errno);
- return msgStr;
- }
-
- msgStr.clear();
- msgStr = msg;
- return msgStr;
-}
-#endif
-
int SnapuserdClient::StopSnapuserd(bool firstStageDaemon) {
if (firstStageDaemon) {
sockfd_ = socket_local_client(GetSocketNameFirstStage().c_str(),
@@ -209,7 +191,8 @@
return 0;
}
-int SnapuserdClient::InitializeSnapuserd(std::string cow_device, std::string backing_device) {
+int SnapuserdClient::InitializeSnapuserd(std::string cow_device, std::string backing_device,
+ std::string control_device) {
int ret = 0;
if (!ConnectToServer()) {
@@ -217,7 +200,7 @@
return -1;
}
- std::string msg = "start," + cow_device + "," + backing_device;
+ std::string msg = "start," + cow_device + "," + backing_device + "," + control_device;
ret = Sendmsg(msg.c_str(), msg.size());
if (ret < 0) {
@@ -270,7 +253,7 @@
* completely active to serve the IO and merging process.
*
*/
-int SnapuserdClient::RestartSnapuserd(std::vector<std::pair<std::string, std::string>>& vec) {
+int SnapuserdClient::RestartSnapuserd(std::vector<std::vector<std::string>>& vec) {
// Connect to first-stage daemon and send a terminate-request control
// message. This will not terminate the daemon but will mark the daemon as
// passive.
@@ -306,14 +289,19 @@
LOG(DEBUG) << "Second stage Snapuserd daemon created successfully at socket "
<< GetSocketNameSecondStage();
- CHECK(vec.size() % 2 == 0);
+ // Vector contains all the device information to be passed to the new
+ // daemon. Note that the caller can choose to initialize separately
+ // by calling InitializeSnapuserd() API as well. In that case, vector
+ // should be empty
for (int i = 0; i < vec.size(); i++) {
- std::string& cow_device = vec[i].first;
- std::string& base_device = vec[i].second;
+ std::string& cow_device = vec[i][0];
+ std::string& base_device = vec[i][1];
+ std::string& control_device = vec[i][2];
- InitializeSnapuserd(cow_device, base_device);
- LOG(DEBUG) << "Daemon initialized with " << cow_device << " and " << base_device;
+ InitializeSnapuserd(cow_device, base_device, control_device);
+ LOG(DEBUG) << "Daemon initialized with " << cow_device << ", " << base_device << " and "
+ << control_device;
}
return 0;
diff --git a/fs_mgr/libsnapshot/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd_server.cpp
index 1f8dd63..53101aa 100644
--- a/fs_mgr/libsnapshot/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_server.cpp
@@ -63,8 +63,9 @@
}
// new thread
-void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_device) {
- Snapuserd snapd(cow_device, backing_device);
+void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_device,
+ std::string control_device) {
+ Snapuserd snapd(cow_device, backing_device, control_device);
if (!snapd.Init()) {
PLOG(ERROR) << "Snapuserd: Init failed";
return;
@@ -73,10 +74,9 @@
while (StopRequested() == false) {
int ret = snapd.Run();
- if (ret == -ETIMEDOUT) continue;
-
if (ret < 0) {
- PLOG(ERROR) << "snapd.Run() failed..." << ret;
+ LOG(ERROR) << "Snapuserd: Thread terminating as control device is de-registered";
+ break;
}
}
}
@@ -159,12 +159,12 @@
switch (op) {
case DaemonOperations::START: {
// Message format:
- // start,<cow_device_path>,<source_device_path>
+ // start,<cow_device_path>,<source_device_path>,<control_device>
//
// Start the new thread which binds to dm-user misc device
newClient = std::make_unique<Client>();
newClient->SetThreadHandler(
- std::bind(&SnapuserdServer::ThreadStart, this, out[1], out[2]));
+ std::bind(&SnapuserdServer::ThreadStart, this, out[1], out[2], out[3]));
clients_vec_.push_back(std::move(newClient));
sprintf(msg, "success");
Sendmsg(fd, msg, MAX_PACKET_SIZE);
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 9edcda7..62ca162 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -177,7 +177,12 @@
return std::make_unique<DmTargetSnapshot>(start_sector, num_sectors, base_device,
cow_device, mode, chunk_size);
} else if (target_type == "user") {
- return std::make_unique<DmTargetUser>(start_sector, num_sectors);
+ if (!HasArgs(1)) {
+ std::cerr << "Expected \"user\" <control_device_name>" << std::endl;
+ return nullptr;
+ }
+ std::string control_device = NextArg();
+ return std::make_unique<DmTargetUser>(start_sector, num_sectors, control_device);
} else {
std::cerr << "Unrecognized target type: " << target_type << std::endl;
return nullptr;
diff --git a/include/backtrace b/include/backtrace
deleted file mode 120000
index 93ce2b1..0000000
--- a/include/backtrace
+++ /dev/null
@@ -1 +0,0 @@
-../libbacktrace/include/backtrace
\ No newline at end of file
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index ceabf62..b3ae937 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -66,6 +66,7 @@
deps.emplace_back(prefix + args[0].substr(0, pos));
} else {
LOG(ERROR) << "dependency lines must start with name followed by ':'";
+ return false;
}
// Remaining items are dependencies of our module
diff --git a/libmodprobe/libmodprobe_test.cpp b/libmodprobe/libmodprobe_test.cpp
index 5919c49..d50c10d 100644
--- a/libmodprobe/libmodprobe_test.cpp
+++ b/libmodprobe/libmodprobe_test.cpp
@@ -179,3 +179,16 @@
m.EnableBlocklist(true);
EXPECT_FALSE(m.LoadWithAliases("test4", true));
}
+
+TEST(libmodprobe, ModuleDepLineWithoutColonIsSkipped) {
+ TemporaryDir dir;
+ auto dir_path = std::string(dir.path);
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "no_colon.ko no_colon.ko\n", dir_path + "/modules.dep", 0600, getuid(), getgid()));
+
+ kernel_cmdline = "";
+ test_modules = {dir_path + "/no_colon.ko"};
+
+ Modprobe m({dir.path});
+ EXPECT_FALSE(m.LoadWithAliases("no_colon", true));
+}
diff --git a/libutils/Android.bp b/libutils/Android.bp
index dd9fea0..e53e89b 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -43,7 +43,13 @@
header_libs: ["libbacktrace_headers"],
export_header_lib_headers: ["libbacktrace_headers"],
},
+ linux_glibc: {
+ header_libs: ["libbacktrace_headers"],
+ export_header_lib_headers: ["libbacktrace_headers"],
+ },
linux_bionic: {
+ header_libs: ["libbacktrace_headers"],
+ export_header_lib_headers: ["libbacktrace_headers"],
enabled: true,
},
windows: {
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index ae10789..2523097 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -21,9 +21,9 @@
#include <android-base/macros.h>
-#include <utils/RefBase.h>
+#include <log/log.h>
-#include <utils/CallStack.h>
+#include <utils/RefBase.h>
#include <utils/Mutex.h>
@@ -55,6 +55,17 @@
// case.
#define DEBUG_REFBASE_DESTRUCTION 1
+#if !defined(_WIN32)
+// CallStack is only supported on linux type platforms.
+#define CALLSTACK_ENABLED 1
+#else
+#define CALLSTACK_ENABLED 0
+#endif
+
+#if CALLSTACK_ENABLED
+#include <utils/CallStack.h>
+#endif
+
// ---------------------------------------------------------------------------
namespace android {
@@ -185,7 +196,7 @@
, mRetain(false)
{
}
-
+
~weakref_impl()
{
bool dumpStack = false;
@@ -196,7 +207,7 @@
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
-#if DEBUG_REFS_CALLSTACK_ENABLED
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
CallStack::logStack(LOG_TAG, refs->stack.get());
#endif
refs = refs->next;
@@ -210,7 +221,7 @@
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
-#if DEBUG_REFS_CALLSTACK_ENABLED
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
CallStack::logStack(LOG_TAG, refs->stack.get());
#endif
refs = refs->next;
@@ -218,7 +229,9 @@
}
if (dumpStack) {
ALOGE("above errors at:");
+#if CALLSTACK_ENABLED
CallStack::logStack(LOG_TAG);
+#endif
}
}
@@ -261,8 +274,7 @@
renameRefsId(mWeakRefs, old_id, new_id);
}
- void trackMe(bool track, bool retain)
- {
+ void trackMe(bool track, bool retain) {
mTrackEnabled = track;
mRetain = retain;
}
@@ -306,7 +318,7 @@
{
ref_entry* next;
const void* id;
-#if DEBUG_REFS_CALLSTACK_ENABLED
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
CallStack::CallStackUPtr stack;
#endif
int32_t ref;
@@ -323,7 +335,7 @@
// decrement the reference count.
ref->ref = mRef;
ref->id = id;
-#if DEBUG_REFS_CALLSTACK_ENABLED
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
ref->stack = CallStack::getCurrent(2);
#endif
ref->next = *refs;
@@ -335,7 +347,7 @@
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
-
+
ref_entry* const head = *refs;
ref_entry* ref = head;
while (ref != NULL) {
@@ -359,7 +371,9 @@
ref = ref->next;
}
+#if CALLSTACK_ENABLED
CallStack::logStack(LOG_TAG);
+#endif
}
}
@@ -385,7 +399,7 @@
snprintf(buf, sizeof(buf), "\t%c ID %p (ref %d):\n",
inc, refs->id, refs->ref);
out->append(buf);
-#if DEBUG_REFS_CALLSTACK_ENABLED
+#if DEBUG_REFS_CALLSTACK_ENABLED && CALLSTACK_ENABLED
out->append(CallStack::stackToString("\t\t", refs->stack.get()));
#else
out->append("\t\t(call stacks disabled)");
@@ -412,7 +426,7 @@
{
weakref_impl* const refs = mRefs;
refs->incWeak(id);
-
+
refs->addStrongRef(id);
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
@@ -468,7 +482,7 @@
// TODO: Better document assumptions.
weakref_impl* const refs = mRefs;
refs->incWeak(id);
-
+
refs->addStrongRef(id);
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
ALOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
@@ -550,7 +564,7 @@
bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
incWeak(id);
-
+
weakref_impl* const impl = static_cast<weakref_impl*>(this);
int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
@@ -567,7 +581,7 @@
// the strong count has changed on us, we need to re-assert our
// situation. curCount was updated by compare_exchange_weak.
}
-
+
if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
// we're now in the harder case of either:
// - there never was a strong reference on us
@@ -624,7 +638,7 @@
}
}
}
-
+
impl->addStrongRef(id);
#if PRINT_REFS
@@ -719,7 +733,10 @@
// Treating this as fatal is prone to causing boot loops. For debugging, it's
// better to treat as non-fatal.
ALOGD("RefBase: Explicit destruction, weak count = %d (in %p)", mRefs->mWeak.load(), this);
+
+#if CALLSTACK_ENABLED
CallStack::logStack(LOG_TAG);
+#endif
#else
LOG_ALWAYS_FATAL("RefBase: Explicit destruction, weak count = %d", mRefs->mWeak.load());
#endif
diff --git a/libutils/SharedBuffer_test.cpp b/libutils/SharedBuffer_test.cpp
index 33a4e0c..3f960d2 100644
--- a/libutils/SharedBuffer_test.cpp
+++ b/libutils/SharedBuffer_test.cpp
@@ -23,36 +23,45 @@
#include "SharedBuffer.h"
-TEST(SharedBufferTest, TestAlloc) {
- EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX), "");
- EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer)), "");
+extern "C" void __hwasan_init() __attribute__((weak));
+#define SKIP_WITH_HWASAN \
+ if (&__hwasan_init != 0) GTEST_SKIP()
- // Make sure we don't die here.
- // Check that null is returned, as we are asking for the whole address space.
- android::SharedBuffer* buf =
- android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer) - 1);
- ASSERT_EQ(nullptr, buf);
-
- buf = android::SharedBuffer::alloc(0);
- ASSERT_NE(nullptr, buf);
- ASSERT_EQ(0U, buf->size());
- buf->release();
+TEST(SharedBufferTest, alloc_death) {
+ EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX), "");
+ EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer)), "");
}
-TEST(SharedBufferTest, TestEditResize) {
- android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
- EXPECT_DEATH(buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer)), "");
- buf = android::SharedBuffer::alloc(10);
- EXPECT_DEATH(buf->editResize(SIZE_MAX), "");
+TEST(SharedBufferTest, alloc_null) {
+ // Big enough to fail, not big enough to abort.
+ SKIP_WITH_HWASAN; // hwasan has a 2GiB allocation limit.
+ ASSERT_EQ(nullptr, android::SharedBuffer::alloc(SIZE_MAX / 2));
+}
- buf = android::SharedBuffer::alloc(10);
- // Make sure we don't die here.
- // Check that null is returned, as we are asking for the whole address space.
- buf = buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer) - 1);
- ASSERT_EQ(nullptr, buf);
+TEST(SharedBufferTest, alloc_zero_size) {
+ android::SharedBuffer* buf = android::SharedBuffer::alloc(0);
+ ASSERT_NE(nullptr, buf);
+ ASSERT_EQ(0U, buf->size());
+ buf->release();
+}
- buf = android::SharedBuffer::alloc(10);
- buf = buf->editResize(0);
- ASSERT_EQ(0U, buf->size());
- buf->release();
+TEST(SharedBufferTest, editResize_death) {
+ android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
+ EXPECT_DEATH(buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer)), "");
+ buf = android::SharedBuffer::alloc(10);
+ EXPECT_DEATH(buf->editResize(SIZE_MAX), "");
+}
+
+TEST(SharedBufferTest, editResize_null) {
+ // Big enough to fail, not big enough to abort.
+ SKIP_WITH_HWASAN; // hwasan has a 2GiB allocation limit.
+ android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
+ ASSERT_EQ(nullptr, buf->editResize(SIZE_MAX / 2));
+}
+
+TEST(SharedBufferTest, editResize_zero_size) {
+ android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
+ buf = buf->editResize(0);
+ ASSERT_EQ(0U, buf->size());
+ buf->release();
}
diff --git a/rootdir/avb/Android.mk b/rootdir/avb/Android.mk
index 3978593..9892ae7 100644
--- a/rootdir/avb/Android.mk
+++ b/rootdir/avb/Android.mk
@@ -2,6 +2,8 @@
ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
my_gsi_avb_keys_path := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else ifeq ($(BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT),true)
+ my_gsi_avb_keys_path := $(TARGET_VENDOR_RAMDISK_OUT)/avb
else
my_gsi_avb_keys_path := $(TARGET_RAMDISK_OUT)/avb
endif
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 7edf3c3..3146f36 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -561,6 +561,11 @@
# Make sure that apexd is started in the default namespace
enter_default_mount_ns
+ mkdir /data/vendor 0771 root root encryption=Require
+ mkdir /data/vendor_ce 0771 root root encryption=None
+ mkdir /data/vendor_de 0771 root root encryption=None
+ mkdir /data/vendor/hardware 0771 root root
+
# Start tombstoned early to be able to store tombstones.
mkdir /data/tombstones 0771 system system encryption=Require
mkdir /data/vendor/tombstones 0771 root root
@@ -653,11 +658,6 @@
mkdir /data/preloads 0775 system system encryption=None
- mkdir /data/vendor 0771 root root encryption=Require
- mkdir /data/vendor_ce 0771 root root encryption=None
- mkdir /data/vendor_de 0771 root root encryption=None
- mkdir /data/vendor/hardware 0771 root root
-
# For security reasons, /data/local/tmp should always be empty.
# Do not place files or directories in /data/local/tmp
mkdir /data/local/tmp 0771 shell shell