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
20 #include "ipc/storage_manager_client.h"
21 #include "storage_service_errno.h"
22 #include "storage_service_log.h"
23 #include "utils/disk_utils.h"
24 #include "utils/file_utils.h"
25
26 namespace OHOS {
27 namespace StorageDaemon {
28 DiskManager* DiskManager::instance_ = nullptr;
29
Instance()30 DiskManager* DiskManager::Instance()
31 {
32 if (instance_ == nullptr) {
33 instance_ = new DiskManager();
34 }
35
36 return instance_;
37 }
38
~DiskManager()39 DiskManager::~DiskManager()
40 {
41 LOGI("Destroy DiskManager");
42 }
43
HandleDiskEvent(NetlinkData * data)44 void DiskManager::HandleDiskEvent(NetlinkData *data)
45 {
46 if (data == nullptr) {
47 LOGE("data is nullptr");
48 return;
49 }
50 std::lock_guard<std::mutex> lock(lock_);
51 std::string devType = data->GetParam("DEVTYPE");
52 if (devType != "disk") {
53 return;
54 }
55
56 unsigned int major = (unsigned int) std::stoi(data->GetParam("MAJOR"));
57 unsigned int minor = (unsigned int) std::stoi(data->GetParam("MINOR"));
58 dev_t device = makedev(major, minor);
59
60 switch (data->GetAction()) {
61 case NetlinkData::Actions::ADD: {
62 auto diskInfo = MatchConfig(data);
63 if (diskInfo == nullptr) {
64 LOGI("Can't match config, devPath is %{public}s", data->GetDevpath().c_str());
65 } else {
66 CreateDisk(diskInfo);
67 LOGI("Handle Disk Add Event");
68 }
69 break;
70 }
71 case NetlinkData::Actions::CHANGE: {
72 ChangeDisk(device, data);
73 LOGI("Handle Disk Change Event");
74 break;
75 }
76 case NetlinkData::Actions::REMOVE: {
77 DestroyDisk(device);
78 LOGI("Handle Disk Remove Event");
79 break;
80 }
81 default: {
82 LOGW("Cannot handle unexpected disk event %{public}d", data->GetAction());
83 break;
84 }
85 }
86 }
87
MatchConfig(NetlinkData * data)88 std::shared_ptr<DiskInfo> DiskManager::MatchConfig(NetlinkData *data)
89 {
90 if (data == nullptr) {
91 LOGE("data is nullptr");
92 return nullptr;
93 }
94 std::string sysPath = data->GetSyspath();
95 std::string devPath = data->GetDevpath();
96 unsigned int major = (unsigned int) std::stoi(data->GetParam("MAJOR"));
97 unsigned int minor = (unsigned int) std::stoi(data->GetParam("MINOR"));
98 dev_t device = makedev(major, minor);
99
100 for (auto config : diskConfig_) {
101 if ((config != nullptr) && config->IsMatch(devPath)) {
102 uint32_t flag = static_cast<uint32_t>(config->GetFlag());
103 if (major == DISK_MMC_MAJOR) {
104 flag |= DiskInfo::DeviceFlag::SD_FLAG;
105 } else {
106 flag |= DiskInfo::DeviceFlag::USB_FLAG;
107 }
108 auto diskInfo = std::make_shared<DiskInfo>(sysPath, devPath, device, static_cast<int>(flag));
109 return diskInfo;
110 }
111 }
112
113 LOGI("No matching configuration found");
114 return nullptr;
115 }
116
CreateDisk(std::shared_ptr<DiskInfo> & diskInfo)117 void DiskManager::CreateDisk(std::shared_ptr<DiskInfo> &diskInfo)
118 {
119 if (diskInfo == nullptr) {
120 LOGE("diskInfo is nullptr");
121 return;
122 }
123
124 int ret = diskInfo->Create();
125 if (ret != E_OK) {
126 LOGE("Create DiskInfo failed");
127 return;
128 }
129 disk_.push_back(diskInfo);
130 }
131
ChangeDisk(dev_t device,NetlinkData * data)132 void DiskManager::ChangeDisk(dev_t device, NetlinkData *data)
133 {
134 for (auto &diskInfo : disk_) {
135 if ((diskInfo != nullptr) && (diskInfo->GetDevice() == device)) {
136 diskInfo->ReadMetadata();
137 diskInfo->ReadPartition();
138 return;
139 }
140 }
141 auto diskInfo = MatchConfig(data);
142 if (diskInfo == nullptr) {
143 LOGI("Can't match config, devPath is %{public}s", data->GetDevpath().c_str());
144 } else {
145 CreateDisk(diskInfo);
146 LOGI("Handle Disk Add Event");
147 }
148 }
149
DestroyDisk(dev_t device)150 void DiskManager::DestroyDisk(dev_t device)
151 {
152 int ret;
153
154 for (auto i = disk_.begin(); i != disk_.end();) {
155 if ((*i)->GetDevice() == device) {
156 ret = (*i)->Destroy();
157 if (ret != E_OK) {
158 LOGE("Destroy DiskInfo failed");
159 return;
160 }
161
162 StorageManagerClient client;
163 ret = client.NotifyDiskDestroyed((*i)->GetId());
164 if (ret != E_OK) {
165 LOGI("Notify Disk Destroyed failed");
166 }
167 i = disk_.erase(i);
168 } else {
169 i++;
170 }
171 }
172 }
173
GetDisk(dev_t device)174 std::shared_ptr<DiskInfo> DiskManager::GetDisk(dev_t device)
175 {
176 for (auto &diskInfo : disk_) {
177 if ((diskInfo != nullptr) && (diskInfo->GetDevice() == device)) {
178 return diskInfo;
179 }
180 }
181
182 LOGI("No disk found with the given device");
183 return nullptr;
184 }
185
AddDiskConfig(std::shared_ptr<DiskConfig> & diskConfig)186 void DiskManager::AddDiskConfig(std::shared_ptr<DiskConfig> &diskConfig)
187 {
188 std::lock_guard<std::mutex> lock(lock_);
189 if (diskConfig != nullptr) {
190 diskConfig_.push_back(diskConfig);
191 }
192 }
193
ReplayUevent()194 void DiskManager::ReplayUevent()
195 {
196 TraverseDirUevent(sysBlockPath_, true);
197 }
198
HandlePartition(std::string diskId)199 int32_t DiskManager::HandlePartition(std::string diskId)
200 {
201 int32_t ret = E_NON_EXIST;
202
203 for (auto i = disk_.begin(); i != disk_.end(); i++) {
204 if (*i == nullptr) {
205 continue;
206 }
207
208 if ((*i)->GetId() == diskId) {
209 ret = (*i)->Partition();
210 break;
211 }
212 }
213
214 return ret;
215 }
216 } // namespace STORAGE_DAEMON
217 } // namespace OHOS
218