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