1*33f37583SAndroid Build Coastguard Worker /*
2*33f37583SAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project
3*33f37583SAndroid Build Coastguard Worker *
4*33f37583SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*33f37583SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*33f37583SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*33f37583SAndroid Build Coastguard Worker *
8*33f37583SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*33f37583SAndroid Build Coastguard Worker *
10*33f37583SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*33f37583SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*33f37583SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*33f37583SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*33f37583SAndroid Build Coastguard Worker * limitations under the License.
15*33f37583SAndroid Build Coastguard Worker */
16*33f37583SAndroid Build Coastguard Worker
17*33f37583SAndroid Build Coastguard Worker #include "apexd_dm.h"
18*33f37583SAndroid Build Coastguard Worker
19*33f37583SAndroid Build Coastguard Worker #include <ApexProperties.sysprop.h>
20*33f37583SAndroid Build Coastguard Worker #include <android-base/logging.h>
21*33f37583SAndroid Build Coastguard Worker #include <utils/Trace.h>
22*33f37583SAndroid Build Coastguard Worker
23*33f37583SAndroid Build Coastguard Worker using android::base::ErrnoError;
24*33f37583SAndroid Build Coastguard Worker using android::base::Error;
25*33f37583SAndroid Build Coastguard Worker using android::base::Result;
26*33f37583SAndroid Build Coastguard Worker using android::dm::DeviceMapper;
27*33f37583SAndroid Build Coastguard Worker using android::dm::DmDeviceState;
28*33f37583SAndroid Build Coastguard Worker using android::dm::DmTable;
29*33f37583SAndroid Build Coastguard Worker
30*33f37583SAndroid Build Coastguard Worker namespace android::apex {
31*33f37583SAndroid Build Coastguard Worker
~DmDevice()32*33f37583SAndroid Build Coastguard Worker DmDevice::~DmDevice() {
33*33f37583SAndroid Build Coastguard Worker if (!cleared_) {
34*33f37583SAndroid Build Coastguard Worker Result<void> ret = DeleteDmDevice(name_, /* deferred= */ false);
35*33f37583SAndroid Build Coastguard Worker if (!ret.ok()) {
36*33f37583SAndroid Build Coastguard Worker LOG(ERROR) << ret.error();
37*33f37583SAndroid Build Coastguard Worker }
38*33f37583SAndroid Build Coastguard Worker }
39*33f37583SAndroid Build Coastguard Worker }
40*33f37583SAndroid Build Coastguard Worker
CreateDmDeviceInternal(DeviceMapper & dm,const std::string & name,const DmTable & table,const std::chrono::milliseconds & timeout)41*33f37583SAndroid Build Coastguard Worker static Result<DmDevice> CreateDmDeviceInternal(
42*33f37583SAndroid Build Coastguard Worker DeviceMapper& dm, const std::string& name, const DmTable& table,
43*33f37583SAndroid Build Coastguard Worker const std::chrono::milliseconds& timeout) {
44*33f37583SAndroid Build Coastguard Worker std::string dev_path;
45*33f37583SAndroid Build Coastguard Worker if (!dm.CreateDevice(name, table, &dev_path, timeout)) {
46*33f37583SAndroid Build Coastguard Worker return Error() << "Couldn't create dm-device.";
47*33f37583SAndroid Build Coastguard Worker }
48*33f37583SAndroid Build Coastguard Worker return DmDevice(name, dev_path);
49*33f37583SAndroid Build Coastguard Worker }
50*33f37583SAndroid Build Coastguard Worker
CreateDmDevice(const std::string & name,const DmTable & table,bool reuse_device)51*33f37583SAndroid Build Coastguard Worker Result<DmDevice> CreateDmDevice(const std::string& name, const DmTable& table,
52*33f37583SAndroid Build Coastguard Worker bool reuse_device) {
53*33f37583SAndroid Build Coastguard Worker ATRACE_NAME("CreateDmDevice");
54*33f37583SAndroid Build Coastguard Worker LOG(VERBOSE) << "Creating dm-device " << name;
55*33f37583SAndroid Build Coastguard Worker
56*33f37583SAndroid Build Coastguard Worker auto timeout = std::chrono::milliseconds(
57*33f37583SAndroid Build Coastguard Worker android::sysprop::ApexProperties::dm_create_timeout().value_or(1000));
58*33f37583SAndroid Build Coastguard Worker
59*33f37583SAndroid Build Coastguard Worker DeviceMapper& dm = DeviceMapper::Instance();
60*33f37583SAndroid Build Coastguard Worker
61*33f37583SAndroid Build Coastguard Worker auto state = dm.GetState(name);
62*33f37583SAndroid Build Coastguard Worker if (state == DmDeviceState::INVALID) {
63*33f37583SAndroid Build Coastguard Worker return CreateDmDeviceInternal(dm, name, table, timeout);
64*33f37583SAndroid Build Coastguard Worker }
65*33f37583SAndroid Build Coastguard Worker
66*33f37583SAndroid Build Coastguard Worker if (reuse_device) {
67*33f37583SAndroid Build Coastguard Worker if (state == DmDeviceState::ACTIVE) {
68*33f37583SAndroid Build Coastguard Worker LOG(WARNING) << "Deleting existing active dm-device " << name;
69*33f37583SAndroid Build Coastguard Worker OR_RETURN(DeleteDmDevice(name, /* deferred= */ false));
70*33f37583SAndroid Build Coastguard Worker return CreateDmDeviceInternal(dm, name, table, timeout);
71*33f37583SAndroid Build Coastguard Worker }
72*33f37583SAndroid Build Coastguard Worker if (!dm.LoadTableAndActivate(name, table)) {
73*33f37583SAndroid Build Coastguard Worker dm.DeleteDevice(name);
74*33f37583SAndroid Build Coastguard Worker return Error() << "Failed to activate dm-device " << name;
75*33f37583SAndroid Build Coastguard Worker }
76*33f37583SAndroid Build Coastguard Worker std::string path;
77*33f37583SAndroid Build Coastguard Worker if (!dm.WaitForDevice(name, timeout, &path)) {
78*33f37583SAndroid Build Coastguard Worker dm.DeleteDevice(name);
79*33f37583SAndroid Build Coastguard Worker return Error() << "Failed waiting for dm-device " << name;
80*33f37583SAndroid Build Coastguard Worker }
81*33f37583SAndroid Build Coastguard Worker return DmDevice(name, path);
82*33f37583SAndroid Build Coastguard Worker } else {
83*33f37583SAndroid Build Coastguard Worker // Delete dangling dm-device. This can happen if apexd fails to delete it
84*33f37583SAndroid Build Coastguard Worker // while unmounting an apex.
85*33f37583SAndroid Build Coastguard Worker LOG(WARNING) << "Deleting existing dm-device " << name;
86*33f37583SAndroid Build Coastguard Worker OR_RETURN(DeleteDmDevice(name, /* deferred= */ false));
87*33f37583SAndroid Build Coastguard Worker return CreateDmDeviceInternal(dm, name, table, timeout);
88*33f37583SAndroid Build Coastguard Worker }
89*33f37583SAndroid Build Coastguard Worker }
90*33f37583SAndroid Build Coastguard Worker
91*33f37583SAndroid Build Coastguard Worker // Deletes a device-mapper device with a given name and path
92*33f37583SAndroid Build Coastguard Worker // Synchronizes on the device actually being deleted from userspace.
DeleteDmDevice(const std::string & name,bool deferred)93*33f37583SAndroid Build Coastguard Worker Result<void> DeleteDmDevice(const std::string& name, bool deferred) {
94*33f37583SAndroid Build Coastguard Worker DeviceMapper& dm = DeviceMapper::Instance();
95*33f37583SAndroid Build Coastguard Worker if (deferred) {
96*33f37583SAndroid Build Coastguard Worker if (!dm.DeleteDeviceDeferred(name)) {
97*33f37583SAndroid Build Coastguard Worker return ErrnoError() << "Failed to issue deferred delete of dm-device "
98*33f37583SAndroid Build Coastguard Worker << name;
99*33f37583SAndroid Build Coastguard Worker }
100*33f37583SAndroid Build Coastguard Worker return {};
101*33f37583SAndroid Build Coastguard Worker }
102*33f37583SAndroid Build Coastguard Worker auto timeout = std::chrono::milliseconds(
103*33f37583SAndroid Build Coastguard Worker android::sysprop::ApexProperties::dm_delete_timeout().value_or(750));
104*33f37583SAndroid Build Coastguard Worker if (!dm.DeleteDevice(name, timeout)) {
105*33f37583SAndroid Build Coastguard Worker return Error() << "Failed to delete dm-device " << name;
106*33f37583SAndroid Build Coastguard Worker }
107*33f37583SAndroid Build Coastguard Worker return {};
108*33f37583SAndroid Build Coastguard Worker }
109*33f37583SAndroid Build Coastguard Worker
110*33f37583SAndroid Build Coastguard Worker } // namespace android::apex