volume: add volume manager

Signed-off-by: Xu Jia <xujia39@huawei.com>
Change-Id: I1cd9cb05b5459868d689b539c4580f7edb092351
This commit is contained in:
Xu Jia 2022-02-09 11:51:38 +08:00
parent 12be74d265
commit f94b280862
7 changed files with 429 additions and 4 deletions

View File

@ -34,7 +34,8 @@
"fsck_msdos",
"gptfdisk",
"newfs_msdos",
"ntfs-3g"
"ntfs-3g",
"e2fsprogs"
]
},
"build": {
@ -51,7 +52,8 @@
"//third_party/fsck_msdos:fsck_msdos",
"//third_party/gptfdisk:sgdisk",
"//third_party/newfs_msdos:newfs_msdos",
"//third_party/ntfs-3g:ntfsprogs"
"//third_party/ntfs-3g:ntfsprogs",
"//third_party/e2fsprogs/misc:blkid"
],
"inner_kits": [
{

View File

@ -54,6 +54,8 @@ ohos_executable("storage_daemon") {
"disk/src/disk_config.cpp",
"disk/src/disk_info.cpp",
"disk/src/disk_manager.cpp",
"volume/src/volume_info.cpp",
"volume/src/volume_manager.cpp",
"ipc/src/storage_daemon.cpp",
"ipc/src/storage_daemon_stub.cpp",
"ipc/src/storage_manager_client.cpp",

View File

@ -16,9 +16,60 @@
#ifndef OHOS_STORAGE_DAEMON_VOLUME_INFO_H
#define OHOS_STORAGE_DAEMON_VOLUME_INFO_H
#include <string>
#include <sys/types.h>
namespace OHOS {
namespace StorageDaemon {
enum VolumeState {
UNMOUNTED,
CHECKING,
MOUNTED,
EJECTING,
REMOVED,
BADREMOVABLE,
};
enum VolumeType {
EXTERNAL,
};
class VolumeInfo {
public:
VolumeInfo() = default;
virtual ~VolumeInfo() = default;
int32_t Create(const std::string volId, const std::string diskId, dev_t device);
int32_t Destroy();
int32_t Mount(uint32_t flags);
int32_t UMount(bool force = false);
int32_t Check();
int32_t Format(const std::string type);
std::string GetVolumeId();
int32_t GetVolumeType();
std::string GetDiskId();
int32_t GetState();
std::string GetMountPath();
protected:
virtual int32_t DoCreate(dev_t dev) = 0;
virtual int32_t DoDestroy() = 0;
virtual int32_t DoMount(const std::string mountPath, uint32_t mountFlags) = 0;
virtual int32_t DoUMount(const std::string mountPath, bool force) = 0;
virtual int32_t DoCheck() = 0;
virtual int32_t DoFormat(std::string type) = 0;
private:
std::string id_;
std::string diskId_;
VolumeType type_;
VolumeState mountState_;
int32_t mountFlags_;
int32_t userIdOwner_;
std::string mountPath_;
const std::string mountPathDir_ = "/mnt/%s";
};
} // STORAGE_DAEMON
} // OHOS

View File

@ -17,16 +17,35 @@
#define OHOS_STORAGE_DAEMON_VOLUME_MANAGER_H
#include <nocopyable.h>
#include <sys/types.h>
#include <string>
#include <list>
#include <memory>
#include "volume/volume_info.h"
namespace OHOS {
namespace StorageDaemon {
class VolumeManager final {
public:
virtual ~VolumeManager();
virtual ~VolumeManager() = default;
static VolumeManager* Instance();
std::string CreateVolume(const std::string diskId, dev_t device);
int32_t DestroyVolume(const std::string volId);
int32_t Check(const std::string volId);
int32_t Mount(const std::string volId, uint32_t flags);
int32_t UMount(const std::string volId);
int32_t Format(const std::string volId, const std::string fsType);
private:
VolumeManager();
VolumeManager() = default;
DISALLOW_COPY_AND_MOVE(VolumeManager);
static VolumeManager* instance_;
std::list<std::shared_ptr<VolumeInfo>> volumes_;
std::shared_ptr<VolumeInfo> GetVolume(const std::string volId);
};
} // STORAGE_DAEMON
} // OHOS

View File

@ -0,0 +1,193 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "volume/volume_info.h"
#include <cstdlib>
#include <sys/stat.h>
#include "storage_service_log.h"
#include "storage_service_errno.h"
#include "utils/string_utils.h"
using namespace std;
namespace OHOS {
namespace StorageDaemon {
int32_t VolumeInfo::Create(const std::string volId, const std::string diskId, dev_t device)
{
id_ = volId;
diskId_ = diskId;
type_ = EXTERNAL;
mountState_ = UNMOUNTED;
mountFlags_ = 0;
userIdOwner_ = 0;
mountPath_ = StringPrintf(mountPathDir_.c_str(), id_.c_str());
int32_t err = DoCreate(device);
if (err) {
return err;
}
return E_OK;
}
std::string VolumeInfo::GetVolumeId()
{
return id_;
}
int32_t VolumeInfo::GetVolumeType()
{
return type_;
}
std::string VolumeInfo::GetDiskId()
{
return diskId_;
}
int32_t VolumeInfo::GetState()
{
return mountState_;
}
std::string VolumeInfo::GetMountPath()
{
return mountPath_;
}
int32_t VolumeInfo::Destroy()
{
VolumeState state = REMOVED;
if (mountState_ == REMOVED || mountState_ == BADREMOVABLE) {
return E_OK;
}
if (mountState_ != UNMOUNTED) {
// force umount
UMount(true);
state = BADREMOVABLE;
}
int32_t err = DoDestroy();
if (err) {
return err;
}
mountState_ = state;
return E_OK;
}
int32_t VolumeInfo::Mount(uint32_t flags)
{
struct stat statbuf;
int32_t err = 0;
if (mountState_ == MOUNTED) {
return E_OK;
}
if (mountState_ != CHECKING) {
LOGE("please check volume %{public}s first", GetVolumeId().c_str());
return E_VOL_STATE;
}
// check if dir exists
err = lstat(mountPath_.c_str(), &statbuf);
if (!err) {
LOGE("volume mount path %{public}s exists, please remove first", GetMountPath().c_str());
return E_MOUNT;
}
err = mkdir(mountPath_.c_str(), S_IRWXU);
if (err) {
LOGE("the volume %{public}s create mount file %{public}s failed",
GetVolumeId().c_str(), GetMountPath().c_str());
return E_MOUNT;
}
mountFlags_ = flags;
err = DoMount(mountPath_, mountFlags_);
if (err) {
remove(mountPath_.c_str());
return err;
}
mountState_ = MOUNTED;
return E_OK;
}
int32_t VolumeInfo::UMount(bool force)
{
int32_t err = 0;
if (mountState_ == REMOVED || mountState_ == BADREMOVABLE) {
LOGE("the volume %{public}s is in REMOVED state", GetVolumeId().c_str());
return E_VOL_STATE;
}
if (mountState_ == UNMOUNTED) {
return E_OK;
}
if (mountState_ == CHECKING) {
mountState_ = UNMOUNTED;
return E_OK;
}
if (mountState_ == EJECTING && !force) {
return E_WAIT;
}
mountState_ = EJECTING;
err = DoUMount(mountPath_, force);
if (!force && err) {
mountState_ = MOUNTED;
return err;
}
mountState_ = UNMOUNTED;
return E_OK;
}
int32_t VolumeInfo::Check()
{
if (mountState_ != UNMOUNTED) {
LOGE("the volume %{public}s is not in UNMOUNT state", GetVolumeId().c_str());
return E_VOL_STATE;
}
if (mountState_ == CHECKING) {
mountState_ = UNMOUNTED;
}
int32_t err = DoCheck();
if (err) {
return err;
}
mountState_ = CHECKING;
return E_OK;
}
int32_t VolumeInfo::Format(std::string type)
{
if (mountState_ != UNMOUNTED) {
LOGE("Please unmount the volume %{public}s first", GetVolumeId().c_str());
return E_VOL_STATE;
}
int32_t err = DoFormat(type);
if (err) {
return err;
}
return E_OK;
}
} // StorageDaemon
} // OHOS

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "volume/volume_manager.h"
#include <cstdlib>
#include <sys/sysmacros.h>
#include "storage_service_log.h"
#include "storage_service_errno.h"
#include "utils/string_utils.h"
#include "volume/external_volume_info.h"
using namespace std;
namespace OHOS {
namespace StorageDaemon {
VolumeManager* VolumeManager::instance_ = nullptr;
VolumeManager* VolumeManager::Instance()
{
if (instance_ == nullptr) {
instance_ = new VolumeManager();
}
return instance_;
}
std::shared_ptr<VolumeInfo> VolumeManager::GetVolume(const std::string volId)
{
for (std::list<std::shared_ptr<VolumeInfo>>::iterator it = volumes_.begin();
it != volumes_.end(); ++it) {
if ((*it)->GetVolumeId() == volId) {
return (*it);
}
}
return nullptr;
}
std::string VolumeManager::CreateVolume(const std::string diskId, dev_t device)
{
std::string volId = StringPrintf("vol-%u-%u", major(device), minor(device));
LOGI("create volume %{public}s.", volId.c_str());
std::shared_ptr<VolumeInfo> tmp = GetVolume(volId);
if (tmp != nullptr) {
LOGE("volume %{public}s exist.", volId.c_str());
return "";
}
auto info = std::make_shared<ExternalVolumeInfo>();
int32_t ret = info->Create(volId, diskId, device);
if (ret) {
return "";
}
volumes_.push_back(info);
return volId;
}
int32_t VolumeManager::DestroyVolume(const std::string volId)
{
LOGI("destroy volume %{public}s.", volId.c_str());
std::shared_ptr<VolumeInfo> destroyNode = GetVolume(volId);
if (destroyNode == nullptr) {
LOGE("the volume %{public}s does not exist", volId.c_str());
return E_NON_EXIST;
}
int32_t ret = destroyNode->Destroy();
if (ret)
return ret;
volumes_.remove(destroyNode);
destroyNode.reset();
return E_OK;
}
int32_t VolumeManager::Check(const std::string volId)
{
std::shared_ptr<VolumeInfo> info = GetVolume(volId);
if (info == nullptr) {
LOGE("the volume %{public}s does not exist.", volId.c_str());
return E_NON_EXIST;
}
int32_t err = info->Check();
if (err != E_OK) {
LOGE("the volume %{public}s check failed.", volId.c_str());
return err;
}
return E_OK;
}
int32_t VolumeManager::Mount(const std::string volId, uint32_t flags)
{
std::shared_ptr<VolumeInfo> info = GetVolume(volId);
if (info == nullptr) {
LOGE("the volume %{public}s does not exist.", volId.c_str());
return E_NON_EXIST;
}
int32_t err = info->Mount(flags);
if (err != E_OK) {
LOGE("the volume %{public}s mount failed.", volId.c_str());
return err;
}
return E_OK;
}
int32_t VolumeManager::UMount(const std::string volId)
{
std::shared_ptr<VolumeInfo> info = GetVolume(volId);
if (info == nullptr) {
LOGE("the volume %{public}s does not exist.", volId.c_str());
return E_NON_EXIST;
}
int32_t err = info->UMount();
if (err != E_OK) {
LOGE("the volume %{public}s mount failed.", volId.c_str());
return err;
}
return E_OK;
}
int32_t VolumeManager::Format(const std::string volId, const std::string fsType)
{
std::shared_ptr<VolumeInfo> info = GetVolume(volId);
if (info == nullptr) {
LOGE("the volume %{public}s does not exist.", volId.c_str());
return E_NON_EXIST;
}
int32_t err = info->Format(fsType);
if (err != E_OK) {
LOGE("the volume %{public}s format failed.", volId.c_str());
return err;
}
return E_OK;
}
} // StorageDaemon
} // OHOS

View File

@ -34,6 +34,9 @@ enum ErrNo {
E_UMOUNT, // umount error
E_SET_POLICY,
E_USERID_RANGE, // id out or range
E_VOL_STATE, // volume state check fail
E_WAIT, // wait
E_NOT_SUPPORT, // not support
};
}