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 "user/mount_manager.h"
17 #include <cstdlib>
18 #include <sys/mount.h>
19 #include "ipc/istorage_daemon.h"
20 #include "parameter.h"
21 #include "storage_service_errno.h"
22 #include "storage_service_log.h"
23 #include "utils/file_utils.h"
24 #include "utils/mount_argument_utils.h"
25 #include "utils/string_utils.h"
26
27
28 namespace OHOS {
29 namespace StorageDaemon {
30 using namespace std;
31 constexpr int32_t UMOUNT_RETRY_TIMES = 3;
32 std::shared_ptr<MountManager> MountManager::instance_ = nullptr;
33
34 const std::string HMDFS_SYS_CAP = "const.distributed_file_property.enabled";
35 const int32_t HMDFS_VAL_LEN = 6;
MountManager()36 MountManager::MountManager()
37 : hmdfsDirVec_{{"/data/service/el2/%d/hmdfs", 0711, OID_SYSTEM, OID_SYSTEM},
38 {"/data/service/el2/%d/hmdfs/account", 0711, OID_SYSTEM, OID_SYSTEM},
39 {"/data/service/el2/%d/hmdfs/account/files", 02771, OID_USER_DATA_RW, OID_USER_DATA_RW},
40 {"/data/service/el2/%d/hmdfs/account/data", 0711, OID_SYSTEM, OID_SYSTEM},
41 {"/data/service/el2/%d/hmdfs/non_account", 0711, OID_SYSTEM, OID_SYSTEM},
42 {"/data/service/el2/%d/hmdfs/non_account/files", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
43 {"/data/service/el2/%d/hmdfs/non_account/data", 0711, OID_SYSTEM, OID_SYSTEM},
44 {"/data/service/el2/%d/hmdfs/cache", 0711, OID_SYSTEM, OID_SYSTEM},
45 {"/data/service/el2/%d/hmdfs/cache/account_cache", 0711, OID_SYSTEM, OID_SYSTEM},
46 {"/data/service/el2/%d/hmdfs/cache/non_account_cache", 0711, OID_SYSTEM, OID_SYSTEM}},
47 virtualDir_{{"/storage/media/%d", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
48 {"/storage/media/%d/local", 0711, OID_USER_DATA_RW, OID_USER_DATA_RW},
49 {"/mnt/hmdfs/", 0711, OID_ROOT, OID_ROOT},
50 {"/mnt/hmdfs/%d/", 0711, OID_ROOT, OID_ROOT},
51 {"/mnt/hmdfs/%d/account", 0711, OID_ROOT, OID_ROOT},
52 {"/mnt/hmdfs/%d/non_account", 0711, OID_ROOT, OID_ROOT}}
53 {
54 }
55
GetInstance()56 std::shared_ptr<MountManager> MountManager::GetInstance()
57 {
58 static std::once_flag onceFlag;
59 std::call_once(onceFlag, [&]() { instance_ = std::make_shared<MountManager>(); });
60
61 return instance_;
62 }
63
HmdfsTwiceMount(int32_t userId,std::string relativePath)64 int32_t MountManager::HmdfsTwiceMount(int32_t userId, std::string relativePath)
65 {
66 int32_t ret = HmdfsMount(userId, relativePath);
67
68 // bind mount
69 Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
70 ret = Mount(hmdfsMntArgs.GetFullDst() + "/device_view/", hmdfsMntArgs.GetCommFullPath(),
71 nullptr, MS_BIND, nullptr);
72 if (ret != 0 && errno != EEXIST && errno != EBUSY) {
73 LOGE("failed to bind mount, err %{public}d", errno);
74 return E_MOUNT;
75 }
76 return E_OK;
77 }
78
HmdfsMount(int32_t userId,std::string relativePath)79 int32_t MountManager::HmdfsMount(int32_t userId, std::string relativePath)
80 {
81 Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
82 int ret = Mount(hmdfsMntArgs.GetFullSrc(), hmdfsMntArgs.GetFullDst(), "hmdfs",
83 hmdfsMntArgs.GetFlags(), hmdfsMntArgs.OptionsToString().c_str());
84 if (ret != 0 && errno != EEXIST && errno != EBUSY) {
85 LOGE("failed to mount hmdfs, err %{public}d", errno);
86 return E_MOUNT;
87 }
88
89 return E_OK;
90 }
91
HmdfsMount(int32_t userId)92 int32_t MountManager::HmdfsMount(int32_t userId)
93 {
94 int32_t ret = HmdfsTwiceMount(userId, "account");
95
96 ret += HmdfsMount(userId, "non_account");
97 if (ret != E_OK) {
98 return E_MOUNT;
99 }
100
101 return E_OK;
102 }
103
HmdfsTwiceUMount(int32_t userId,std::string relativePath)104 int32_t MountManager::HmdfsTwiceUMount(int32_t userId, std::string relativePath)
105 {
106 int32_t err = E_OK;
107 // un bind mount
108 Utils::MountArgument hmdfsMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
109 err = UMount(hmdfsMntArgs.GetCommFullPath());
110 if (err != E_OK) {
111 LOGE("failed to un bind mount, errno %{public}d, ComDataDir_ dst %{public}s", errno,
112 hmdfsMntArgs.GetCommFullPath().c_str());
113 }
114
115 err = UMount2(hmdfsMntArgs.GetFullDst().c_str(), MNT_DETACH);
116 if (err != E_OK) {
117 LOGE("identical account hmdfs umount failed, errno %{public}d, hmdfs dst %{public}s", errno,
118 hmdfsMntArgs.GetFullDst().c_str());
119 return E_UMOUNT;
120 }
121 return E_OK;
122 }
123
HmdfsUMount(int32_t userId,std::string relativePath)124 int32_t MountManager::HmdfsUMount(int32_t userId, std::string relativePath)
125 {
126 Utils::MountArgument hmdfsAuthMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, relativePath));
127 int32_t ret = UMount2(hmdfsAuthMntArgs.GetFullDst().c_str(), MNT_DETACH);
128 if (ret != E_OK) {
129 LOGE("umount auth hmdfs, errno %{public}d, auth hmdfs dst %{public}s", errno,
130 hmdfsAuthMntArgs.GetFullDst().c_str());
131 return E_UMOUNT;
132 }
133 return E_OK;
134 }
135
HmdfsUMount(int32_t userId)136 int32_t MountManager::HmdfsUMount(int32_t userId)
137 {
138 int32_t ret = HmdfsTwiceUMount(userId, "account");
139 ret += HmdfsUMount(userId, "non_account");
140 if (ret != E_OK) {
141 return E_UMOUNT;
142 }
143 return E_OK;
144 }
145
SupportHmdfs()146 bool MountManager::SupportHmdfs()
147 {
148 char hmdfsEnable[HMDFS_VAL_LEN + 1] = {"false"};
149 int ret = GetParameter(HMDFS_SYS_CAP.c_str(), "", hmdfsEnable, HMDFS_VAL_LEN);
150 LOGI("GetParameter hmdfsEnable %{public}s, ret %{public}d", hmdfsEnable, ret);
151 if (strcmp(hmdfsEnable, "true") == 0) {
152 return true;
153 }
154 return false;
155 }
156
LocalMount(int32_t userId)157 int32_t MountManager::LocalMount(int32_t userId)
158 {
159 Utils::MountArgument LocalMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, "account"));
160 if (Mount(LocalMntArgs.GetFullSrc(), LocalMntArgs.GetCommFullPath() + "local/",
161 nullptr, MS_BIND, nullptr)) {
162 LOGE("failed to bind mount, err %{public}d", errno);
163 return E_MOUNT;
164 }
165 return E_OK;
166 }
167
MountByUser(int32_t userId)168 int32_t MountManager::MountByUser(int32_t userId)
169 {
170 if (CreateVirtualDirs(userId) != E_OK) {
171 LOGE("create hmdfs virtual dir error");
172 return E_PREPARE_DIR;
173 }
174
175 if (!SupportHmdfs()) {
176 return LocalMount(userId);
177 } else {
178 return HmdfsMount(userId);
179 }
180
181 return E_OK;
182 }
183
LocalUMount(int32_t userId)184 int32_t MountManager::LocalUMount(int32_t userId)
185 {
186 Utils::MountArgument LocalMntArgs(Utils::MountArgumentDescriptors::Alpha(userId, "account"));
187 return UMount(LocalMntArgs.GetCommFullPath() + "local/");
188 }
189
UmountByUser(int32_t userId)190 int32_t MountManager::UmountByUser(int32_t userId)
191 {
192 int32_t count = 0;
193 while (count < UMOUNT_RETRY_TIMES) {
194 int32_t err = E_OK;
195 if (!SupportHmdfs()) {
196 err = LocalUMount(userId);
197 } else {
198 err = HmdfsUMount(userId);
199 }
200 if (err == E_OK) {
201 break;
202 } else if (errno == EBUSY) {
203 count++;
204 continue;
205 } else {
206 LOGE("failed to umount, errno %{public}d", errno);
207 return E_UMOUNT;
208 }
209 }
210
211 return E_OK;
212 }
213
PrepareHmdfsDirs(int32_t userId)214 int32_t MountManager::PrepareHmdfsDirs(int32_t userId)
215 {
216 for (const DirInfo &dir : hmdfsDirVec_) {
217 if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
218 return E_PREPARE_DIR;
219 }
220 }
221
222 return E_OK;
223 }
224
CreateVirtualDirs(int32_t userId)225 int32_t MountManager::CreateVirtualDirs(int32_t userId)
226 {
227 for (const DirInfo &dir : virtualDir_) {
228 if (!PrepareDir(StringPrintf(dir.path.c_str(), userId), dir.mode, dir.uid, dir.gid)) {
229 return E_PREPARE_DIR;
230 }
231 }
232
233 return E_OK;
234 }
235
DestroyHmdfsDirs(int32_t userId)236 int32_t MountManager::DestroyHmdfsDirs(int32_t userId)
237 {
238 bool err = true;
239
240 for (const DirInfo &dir : hmdfsDirVec_) {
241 if (IsEndWith(dir.path.c_str(), "%d")) {
242 err &= RmDirRecurse(StringPrintf(dir.path.c_str(), userId));
243 }
244 }
245
246 return err ? E_OK : E_DESTROY_DIR;
247 }
248 } // namespace StorageDaemon
249 } // namespace OHOS
250