VolumeBase.cpp revision 9c48498f4529f623650c56d03e63324c8d813032
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "Utils.h" 18#include "VolumeBase.h" 19#include "VolumeManager.h" 20#include "ResponseCode.h" 21 22#include <base/stringprintf.h> 23#include <base/logging.h> 24 25#include <fcntl.h> 26#include <stdlib.h> 27#include <sys/mount.h> 28#include <sys/stat.h> 29#include <sys/types.h> 30 31using android::base::StringPrintf; 32 33#define DEBUG 1 34 35namespace android { 36namespace vold { 37 38VolumeBase::VolumeBase(Type type) : 39 mType(type), mFlags(0), mUser(-1), mCreated(false), mState(State::kUnmounted) { 40} 41 42VolumeBase::~VolumeBase() { 43 CHECK(!mCreated); 44} 45 46void VolumeBase::setState(State state) { 47 mState = state; 48 49 VolumeManager::Instance()->getBroadcaster()->sendBroadcast( 50 ResponseCode::VolumeStateChanged, 51 StringPrintf("%s %d", getId().c_str(), mState).c_str(), false); 52} 53 54status_t VolumeBase::setFlags(int flags) { 55 if (mState != State::kUnmounted) { 56 LOG(WARNING) << getId() << " flags change requires state unmounted"; 57 return -EBUSY; 58 } 59 60 mFlags = flags; 61 return OK; 62} 63 64status_t VolumeBase::setUser(userid_t user) { 65 if (mState != State::kUnmounted) { 66 LOG(WARNING) << getId() << " user change requires state unmounted"; 67 return -EBUSY; 68 } 69 70 mUser = user; 71 return OK; 72} 73 74status_t VolumeBase::setId(const std::string& id) { 75 if (mCreated) { 76 LOG(WARNING) << getId() << " id change requires not created"; 77 return -EBUSY; 78 } 79 80 mId = id; 81 return OK; 82} 83 84status_t VolumeBase::setPath(const std::string& path) { 85 if (mState != State::kMounting) { 86 LOG(WARNING) << getId() << " path change requires state mounting"; 87 return -EBUSY; 88 } 89 90 mPath = path; 91 VolumeManager::Instance()->getBroadcaster()->sendBroadcast( 92 ResponseCode::VolumePathChanged, 93 StringPrintf("%s %s", getId().c_str(), mPath.c_str()).c_str(), false); 94 return OK; 95} 96 97void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) { 98 mVolumes.push_back(volume); 99} 100 101void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) { 102 mVolumes.remove(volume); 103} 104 105std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) { 106 for (auto vol : mVolumes) { 107 if (vol->getId() == id) { 108 return vol; 109 } 110 } 111 return nullptr; 112} 113 114status_t VolumeBase::create() { 115 CHECK(!mCreated); 116 117 mCreated = true; 118 status_t res = doCreate(); 119 VolumeManager::Instance()->getBroadcaster()->sendBroadcast( 120 ResponseCode::VolumeCreated, 121 StringPrintf("%s %d", getId().c_str(), mType).c_str(), false); 122 return res; 123} 124 125status_t VolumeBase::doCreate() { 126 return OK; 127} 128 129status_t VolumeBase::destroy() { 130 CHECK(mCreated); 131 132 if (mState == State::kMounted) { 133 unmount(); 134 } 135 136 VolumeManager::Instance()->getBroadcaster()->sendBroadcast( 137 ResponseCode::VolumeDestroyed, getId().c_str(), false); 138 status_t res = doDestroy(); 139 mCreated = false; 140 return res; 141} 142 143status_t VolumeBase::doDestroy() { 144 return OK; 145} 146 147status_t VolumeBase::mount() { 148 if (mState != State::kUnmounted) { 149 LOG(WARNING) << getId() << " mount requires state unmounted"; 150 return -EBUSY; 151 } 152 153 setState(State::kMounting); 154 status_t res = doMount(); 155 if (res == OK) { 156 setState(State::kMounted); 157 } else { 158 setState(State::kUnmounted); 159 } 160 161 return res; 162} 163 164status_t VolumeBase::unmount() { 165 if (mState != State::kMounted) { 166 LOG(WARNING) << getId() << " unmount requires state mounted"; 167 return -EBUSY; 168 } 169 170 setState(State::kUnmounting); 171 172 for (auto vol : mVolumes) { 173 if (vol->unmount()) { 174 LOG(WARNING) << getId() << " failed to unmount " << vol->getId() 175 << " stacked above"; 176 } 177 } 178 mVolumes.clear(); 179 180 status_t res = doUnmount(); 181 setState(State::kUnmounted); 182 return res; 183} 184 185status_t VolumeBase::format() { 186 if (mState != State::kUnmounted) { 187 LOG(WARNING) << getId() << " format requires state unmounted"; 188 return -EBUSY; 189 } 190 191 setState(State::kFormatting); 192 status_t res = doFormat(); 193 setState(State::kUnmounted); 194 return res; 195} 196 197status_t VolumeBase::doFormat() { 198 return -ENOTSUP; 199} 200 201} // namespace vold 202} // namespace android 203