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 <thread>
19
20 #include <sys/sysmacros.h>
21
22 #include "storage_service_errno.h"
23 #include "storage_service_log.h"
24 #include "utils/string_utils.h"
25 #include "utils/file_utils.h"
26 #include "utils/disk_utils.h"
27 #include "ipc/storage_manager_client.h"
28
29 namespace OHOS {
30 namespace StorageDaemon {
31 DiskManager* DiskManager::instance_ = nullptr;
32
Instance()33 DiskManager* DiskManager::Instance()
34 {
35 if (instance_ == nullptr) {
36 instance_ = new DiskManager();
37 }
38
39 return instance_;
40 }
41
~DiskManager()42 DiskManager::~DiskManager()
43 {
44 LOGI("Destroy DiskManager");
45 }
46
HandleDiskEvent(NetlinkData * data)47 void DiskManager::HandleDiskEvent(NetlinkData *data)
48 {
49 std::lock_guard<std::mutex> lock(lock_);
50 std::string devType = data->GetParam("DEVTYPE");
51 if (devType != "disk") {
52 return;
53 }
54
55 unsigned int major = (unsigned int) std::stoi(data->GetParam("MAJOR"));
56 unsigned int minor = (unsigned int) std::stoi(data->GetParam("MINOR"));
57 dev_t device = makedev(major, minor);
58
59 switch (data->GetAction()) {
60 case NetlinkData::Actions::ADD: {
61 auto diskInfo = MatchConfig(data);
62 if (diskInfo == nullptr) {
63 LOGE("Can't match config");
64 } else {
65 CreateDisk(diskInfo);
66 LOGI("Handle Disk Add Event");
67 }
68 break;
69 }
70 case NetlinkData::Actions::CHANGE: {
71 ChangeDisk(device);
72 LOGI("Handle Disk Change Event");
73 break;
74 }
75 case NetlinkData::Actions::REMOVE: {
76 DestroyDisk(device);
77 LOGI("Handle Disk Remove Event");
78 break;
79 }
80 default: {
81 LOGW("Cannot handle unexpected disk event %{public}d", data->GetAction());
82 break;
83 }
84 }
85 }
86
MatchConfig(NetlinkData * data)87 std::shared_ptr<DiskInfo> DiskManager::MatchConfig(NetlinkData *data)
88 {
89 std::string sysPath = data->GetSyspath();
90 std::string devPath = data->GetDevpath();
91 unsigned int major = (unsigned int) std::stoi(data->GetParam("MAJOR"));
92 unsigned int minor = (unsigned int) std::stoi(data->GetParam("MINOR"));
93 dev_t device = makedev(major, minor);
94
95 for (auto config : diskConfig_) {
96 if (config->IsMatch(devPath)) {
97 int flag = config->GetFlag();
98 if (major == DISK_MMC_MAJOR) {
99 flag |= DiskInfo::DeviceFlag::SD_FLAG;
100 } else {
101 flag |= DiskInfo::DeviceFlag::USB_FLAG;
102 }
103 auto diskInfo = std::make_shared<DiskInfo>(sysPath, devPath, device, flag);
104 return diskInfo;
105 }
106 }
107
108 return nullptr;
109 }
110
CreateDisk(std::shared_ptr<DiskInfo> & diskInfo)111 void DiskManager::CreateDisk(std::shared_ptr<DiskInfo> &diskInfo)
112 {
113 int ret;
114
115 ret = diskInfo->Create();
116 if (ret != E_OK) {
117 LOGE("Create DiskInfo failed");
118 return;
119 }
120
121 disk_.push_back(diskInfo);
122 }
123
ChangeDisk(dev_t device)124 void DiskManager::ChangeDisk(dev_t device)
125 {
126 for (auto &diskInfo : disk_) {
127 if (diskInfo->GetDevice() == device) {
128 diskInfo->ReadMetadata();
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