1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "disk/disk_manager.h"
17
18 #include <sys/sysmacros.h>
19 #include <thread>
20
21 #include "ipc/storage_manager_client.h"
22 #include "storage_service_errno.h"
23 #include "storage_service_log.h"
24 #include "utils/disk_utils.h"
25 #include "utils/file_utils.h"
26 #include "utils/string_utils.h"
27
28 namespace OHOS {
29 namespace StorageDaemon {
30 DiskManager* DiskManager::instance_ = nullptr;
31
Instance()32 DiskManager* DiskManager::Instance()
33 {
34 if (instance_ == nullptr) {
35 instance_ = new DiskManager();
36 }
37
38 return instance_;
39 }
40
~DiskManager()41 DiskManager::~DiskManager()
42 {
43 LOGI("Destroy DiskManager");
44 }
45
HandleDiskEvent(NetlinkData * data)46 void DiskManager::HandleDiskEvent(NetlinkData *data)
47 {
48 if (data == nullptr) {
49 LOGE("data is nullptr");
50 return;
51 }
52 std::lock_guard<std::mutex> lock(lock_);
53 std::string devType = data->GetParam("DEVTYPE");
54 if (devType != "disk") {
55 return;
56 }
57
58 unsigned int major = (unsigned int) std::stoi(data->GetParam("MAJOR"));
59 unsigned int minor = (unsigned int) std::stoi(data->GetParam("MINOR"));
60 dev_t device = makedev(major, minor);
61
62 switch (data->GetAction()) {
63 case NetlinkData::Actions::ADD: {
64 auto diskInfo = MatchConfig(data);
65 if (diskInfo == nullptr) {
66 LOGI("Can't match config, devPath is %{public}s", data->GetDevpath().c_str());
67 } else {
68 CreateDisk(diskInfo);
69 LOGI("Handle Disk Add Event");
70 }
71 break;
72 }
73 case NetlinkData::Actions::CHANGE: {
74 ChangeDisk(device);
75 LOGI("Handle Disk Change Event");
76 break;
77 }
78 case NetlinkData::Actions::REMOVE: {
79 DestroyDisk(device);
80 LOGI("Handle Disk Remove Event");
81 break;
82 }
83 default: {
84 LOGW("Cannot handle unexpected disk event %{public}d", data->GetAction());
85 break;
86 }
87 }
88 }
89
MatchConfig(NetlinkData * data)90 std::shared_ptr<DiskInfo> DiskManager::MatchConfig(NetlinkData *data)
91 {
92 if (data == nullptr) {
93 LOGE("data is nullptr");
94 return nullptr;
95 }
96 std::string sysPath = data->GetSyspath();
97 std::string devPath = data->GetDevpath();
98 unsigned int major = (unsigned int) std::stoi(data->GetParam("MAJOR"));
99 unsigned int minor = (unsigned int) std::stoi(data->GetParam("MINOR"));
100 dev_t device = makedev(major, minor);
101
102 for (auto config : diskConfig_) {
103 if ((config != nullptr) && config->IsMatch(devPath)) {
104 uint32_t flag = static_cast<uint32_t>(config->GetFlag());
105 if (major == DISK_MMC_MAJOR) {
106 flag |= DiskInfo::DeviceFlag::SD_FLAG;
107 } else {
108 flag |= DiskInfo::DeviceFlag::USB_FLAG;
109 }
110 auto diskInfo = std::make_shared<DiskInfo>(sysPath, devPath, device, static_cast<int>(flag));
111 return diskInfo;
112 }
113 }
114
115 LOGI("No matching configuration found");
116 return nullptr;
117 }
118
CreateDisk(std::shared_ptr<DiskInfo> & diskInfo)119 void DiskManager::CreateDisk(std::shared_ptr<DiskInfo> &diskInfo)
120 {
121 if (diskInfo == nullptr) {
122 LOGE("diskInfo is nullptr");
123 return;
124 }
125
126 int ret = diskInfo->Create();
127 if (ret != E_OK) {
128 LOGE("Create DiskInfo failed");
129 return;
130 }
131
132 disk_.push_back(diskInfo);
133 }
134
ChangeDisk(dev_t device)135 void DiskManager::ChangeDisk(dev_t device)
136 {
137 for (auto &diskInfo : disk_) {
138 if (diskInfo->GetDevice() == device) {
139 diskInfo->ReadMetadata();
140 diskInfo->ReadPartition();
141 }
142 }
143 }
144
DestroyDisk(dev_t device)145 void DiskManager::DestroyDisk(dev_t device)
146 {
147 int ret;
148
149 for (auto i = disk_.begin(); i != disk_.end();) {
150 if ((*i)->GetDevice() == device) {
151 ret = (*i)->Destroy();
152 if (ret != E_OK) {
153 LOGE("Destroy DiskInfo failed");
154 return;
155 }
156
157 StorageManagerClient client;
158 ret = client.NotifyDiskDestroyed((*i)->GetId());
159 if (ret != E_OK) {
160 LOGI("Notify Disk Destroyed failed");
161 }
162 i = disk_.erase(i);
163 } else {
164 i++;
165 }
166 }
167 }
168
GetDisk(dev_t device)169 std::shared_ptr<DiskInfo> DiskManager::GetDisk(dev_t device)
170 {
171 for (auto &diskInfo : disk_) {
172 if ((diskInfo != nullptr) && (diskInfo->GetDevice() == device)) {
173 return diskInfo;
174 }
175 }
176
177 LOGI("No disk found with the given device");
178 return nullptr;
179 }
180
AddDiskConfig(std::shared_ptr<DiskConfig> & diskConfig)181 void DiskManager::AddDiskConfig(std::shared_ptr<DiskConfig> &diskConfig)
182 {
183 std::lock_guard<std::mutex> lock(lock_);
184 if (diskConfig != nullptr) {
185 diskConfig_.push_back(diskConfig);
186 }
187 }
188
ReplayUevent()189 void DiskManager::ReplayUevent()
190 {
191 TraverseDirUevent(sysBlockPath_, true);
192 }
193
HandlePartition(std::string diskId)194 int32_t DiskManager::HandlePartition(std::string diskId)
195 {
196 int32_t ret = E_NON_EXIST;
197
198 for (auto i = disk_.begin(); i != disk_.end(); i++) {
199 if ((*i)->GetId() == diskId) {
200 ret = (*i)->Partition();
201 break;
202 }
203 }
204
205 return ret;
206 }
207 } // namespace STORAGE_DAEMON
208 } // namespace OHOS
209