• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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