diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h index 6331edb61..d495014f9 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h @@ -65,7 +65,7 @@ class Snapuserd final { backing_store_device_(in_backing_store_device), metadata_read_done_(false) {} - int Init(); + bool Init(); int Run(); int ReadDmUserHeader(); int WriteDmUserPayload(size_t size); diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h index 2d9d7294f..535e9235e 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h @@ -14,22 +14,8 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include #include -#include #include #include #include diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_daemon.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_daemon.h index c0d3c5eb9..94542d760 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_daemon.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_daemon.h @@ -14,6 +14,8 @@ #pragma once +#include + #include namespace android { @@ -34,12 +36,17 @@ class Daemon { private: bool is_running_; + std::unique_ptr poll_fd_; + // Signal mask used with ppoll() + sigset_t signal_mask_; Daemon(); Daemon(Daemon const&) = delete; void operator=(Daemon const&) = delete; SnapuserdServer server_; + void MaskAllSignalsExceptIntAndTerm(); + void MaskAllSignals(); static void SignalHandler(int signal); }; diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h index 79b883a57..584fe7154 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h @@ -14,18 +14,6 @@ #pragma once -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include #include #include @@ -89,6 +77,7 @@ class SnapuserdServer : public Stoppable { android::base::unique_fd sockfd_; bool terminating_; std::vector> clients_vec_; + void ThreadStart(std::string cow_device, std::string backing_device) override; void ShutdownThreads(); DaemonOperations Resolveop(std::string& input); @@ -100,8 +89,6 @@ class SnapuserdServer : public Stoppable { bool IsTerminating() { return terminating_; } public: - ~SnapuserdServer() { clients_vec_.clear(); } - SnapuserdServer() { terminating_ = false; } int Start(std::string socketname); @@ -109,6 +96,7 @@ class SnapuserdServer : public Stoppable { int Receivemsg(int fd); int Sendmsg(int fd, char* msg, size_t len); std::string Recvmsg(int fd, int* ret); + android::base::borrowed_fd GetSocketFd() { return sockfd_; } }; } // namespace snapshot diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp index 34481b779..3ed853f29 100644 --- a/fs_mgr/libsnapshot/snapuserd.cpp +++ b/fs_mgr/libsnapshot/snapuserd.cpp @@ -485,17 +485,17 @@ int Snapuserd::WriteDmUserPayload(size_t size) { return sizeof(struct dm_user_header) + size; } -int Snapuserd::Init() { +bool Snapuserd::Init() { backing_store_fd_.reset(open(backing_store_device_.c_str(), O_RDONLY)); if (backing_store_fd_ < 0) { LOG(ERROR) << "Open Failed: " << backing_store_device_; - return 1; + return false; } cow_fd_.reset(open(cow_device_.c_str(), O_RDWR)); if (cow_fd_ < 0) { LOG(ERROR) << "Open Failed: " << cow_device_; - return 1; + return false; } std::string str(cow_device_); @@ -509,7 +509,7 @@ int Snapuserd::Init() { std::string uuid; if (!dm.GetDmDeviceUuidByName(device_name, &uuid)) { LOG(ERROR) << "Unable to find UUID for " << cow_device_; - return 1; + return false; } LOG(DEBUG) << "UUID: " << uuid; @@ -518,7 +518,7 @@ int Snapuserd::Init() { ctrl_fd_.reset(open(t.control_path().c_str(), O_RDWR)); if (ctrl_fd_ < 0) { LOG(ERROR) << "Unable to open " << t.control_path(); - return 1; + return false; } // Allocate the buffer which is used to communicate between @@ -528,7 +528,7 @@ int Snapuserd::Init() { size_t buf_size = sizeof(struct dm_user_header) + PAYLOAD_SIZE; bufsink_.Initialize(buf_size); - return 0; + return true; } int Snapuserd::Run() { @@ -601,6 +601,11 @@ int Snapuserd::Run() { ret = ReadData(chunk + num_chunks_read, read_size); if (ret < 0) { LOG(ERROR) << "ReadData failed"; + // TODO: Bug 168259959: All the error paths from this function + // should send error code to dm-user thereby IO + // terminates with an error from dm-user. Returning + // here without sending error code will block the + // IO. return ret; } } @@ -622,7 +627,7 @@ int Snapuserd::Run() { } case DM_USER_MAP_WRITE: { - // TODO: After merge operation is completed, kernel issues write + // TODO: Bug: 168311203: After merge operation is completed, kernel issues write // to flush all the exception mappings where the merge is // completed. If dm-user routes the WRITE IO, we need to clear // in-memory data structures representing those exception diff --git a/fs_mgr/libsnapshot/snapuserd_client.cpp b/fs_mgr/libsnapshot/snapuserd_client.cpp index b10de3572..bef8f5c8b 100644 --- a/fs_mgr/libsnapshot/snapuserd_client.cpp +++ b/fs_mgr/libsnapshot/snapuserd_client.cpp @@ -1,3 +1,33 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #include #include @@ -67,6 +97,37 @@ int SnapuserdClient::Sendmsg(const char* msg, size_t size) { return 0; } +std::string SnapuserdClient::Receivemsg() { + int ret; + struct timeval tv; + fd_set set; + char msg[PACKET_SIZE]; + std::string msgStr("fail"); + + tv.tv_sec = 2; + tv.tv_usec = 0; + FD_ZERO(&set); + FD_SET(sockfd_, &set); + ret = select(sockfd_ + 1, &set, NULL, NULL, &tv); + if (ret == -1) { // select failed + LOG(ERROR) << "Snapuserd:client: Select call failed"; + } else if (ret == 0) { // timeout + LOG(ERROR) << "Snapuserd:client: Select call timeout"; + } else { + ret = TEMP_FAILURE_RETRY(recv(sockfd_, msg, PACKET_SIZE, 0)); + if (ret < 0) { + PLOG(ERROR) << "Snapuserd:client: recv failed"; + } else if (ret == 0) { + LOG(DEBUG) << "Snapuserd:client disconnected"; + } else { + msgStr.clear(); + msgStr = msg; + } + } + return msgStr; +} + +#if 0 std::string SnapuserdClient::Receivemsg() { char msg[PACKET_SIZE]; std::string msgStr("fail"); @@ -82,6 +143,7 @@ std::string SnapuserdClient::Receivemsg() { msgStr = msg; return msgStr; } +#endif int SnapuserdClient::StopSnapuserd(bool firstStageDaemon) { if (firstStageDaemon) { diff --git a/fs_mgr/libsnapshot/snapuserd_daemon.cpp b/fs_mgr/libsnapshot/snapuserd_daemon.cpp index c1008b940..8e7661896 100644 --- a/fs_mgr/libsnapshot/snapuserd_daemon.cpp +++ b/fs_mgr/libsnapshot/snapuserd_daemon.cpp @@ -1,3 +1,19 @@ +/* + * 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 #include @@ -16,11 +32,27 @@ int Daemon::StartServer(std::string socketname) { return ret; } +void Daemon::MaskAllSignalsExceptIntAndTerm() { + sigset_t signal_mask; + sigfillset(&signal_mask); + sigdelset(&signal_mask, SIGINT); + sigdelset(&signal_mask, SIGTERM); + sigdelset(&signal_mask, SIGPIPE); + if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) { + PLOG(ERROR) << "Failed to set sigprocmask"; + } +} + +void Daemon::MaskAllSignals() { + sigset_t signal_mask; + sigfillset(&signal_mask); + if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) { + PLOG(ERROR) << "Couldn't mask all signals"; + } +} + Daemon::Daemon() { is_running_ = true; - // TODO: Mask other signals - Bug 168258493 - signal(SIGINT, Daemon::SignalHandler); - signal(SIGTERM, Daemon::SignalHandler); } bool Daemon::IsRunning() { @@ -28,10 +60,41 @@ bool Daemon::IsRunning() { } void Daemon::Run() { + poll_fd_ = std::make_unique(); + poll_fd_->fd = server_.GetSocketFd().get(); + poll_fd_->events = POLLIN; + + sigfillset(&signal_mask_); + sigdelset(&signal_mask_, SIGINT); + sigdelset(&signal_mask_, SIGTERM); + + // Masking signals here ensure that after this point, we won't handle INT/TERM + // until after we call into ppoll() + MaskAllSignals(); + signal(SIGINT, Daemon::SignalHandler); + signal(SIGTERM, Daemon::SignalHandler); + signal(SIGPIPE, Daemon::SignalHandler); + + LOG(DEBUG) << "Snapuserd-server: ready to accept connections"; + while (IsRunning()) { - if (server_.AcceptClient() == static_cast(DaemonOperations::STOP)) { - Daemon::Instance().is_running_ = false; + int ret = ppoll(poll_fd_.get(), 1, nullptr, &signal_mask_); + MaskAllSignalsExceptIntAndTerm(); + + if (ret == -1) { + PLOG(ERROR) << "Snapuserd:ppoll error"; + break; } + + if (poll_fd_->revents == POLLIN) { + if (server_.AcceptClient() == static_cast(DaemonOperations::STOP)) { + Daemon::Instance().is_running_ = false; + } + } + + // Mask all signals to ensure that is_running_ can't become false between + // checking it in the while condition and calling into ppoll() + MaskAllSignals(); } } @@ -43,6 +106,10 @@ void Daemon::SignalHandler(int signal) { Daemon::Instance().is_running_ = false; break; } + case SIGPIPE: { + LOG(ERROR) << "Received SIGPIPE signal"; + break; + } default: LOG(ERROR) << "Received unknown signal " << signal; break; diff --git a/fs_mgr/libsnapshot/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd_server.cpp index 1e8b642d3..1f8dd6359 100644 --- a/fs_mgr/libsnapshot/snapuserd_server.cpp +++ b/fs_mgr/libsnapshot/snapuserd_server.cpp @@ -1,3 +1,30 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -38,9 +65,9 @@ void SnapuserdServer::Parsemsg(std::string const& msg, const char delim, // new thread void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_device) { Snapuserd snapd(cow_device, backing_device); - if (snapd.Init()) { + if (!snapd.Init()) { PLOG(ERROR) << "Snapuserd: Init failed"; - exit(EXIT_FAILURE); + return; } while (StopRequested() == false) {