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