VolumeBase.cpp revision 1d6fbcc389ecb9f418076e8ab5f4c93a5d911de9
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), mMountFlags(0), mMountUserId(-1), mCreated(false), mState( 40 State::kUnmounted), mSilent(false) { 41} 42 43VolumeBase::~VolumeBase() { 44 CHECK(!mCreated); 45} 46 47void VolumeBase::setState(State state) { 48 mState = state; 49 notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState)); 50} 51 52status_t VolumeBase::setDiskId(const std::string& diskId) { 53 if (mCreated) { 54 LOG(WARNING) << getId() << " diskId change requires destroyed"; 55 return -EBUSY; 56 } 57 58 mDiskId = diskId; 59 return OK; 60} 61 62status_t VolumeBase::setMountFlags(int mountFlags) { 63 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) { 64 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable"; 65 return -EBUSY; 66 } 67 68 mMountFlags = mountFlags; 69 return OK; 70} 71 72status_t VolumeBase::setMountUserId(userid_t mountUserId) { 73 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) { 74 LOG(WARNING) << getId() << " user change requires state unmounted or unmountable"; 75 return -EBUSY; 76 } 77 78 mMountUserId = mountUserId; 79 return OK; 80} 81 82status_t VolumeBase::setSilent(bool silent) { 83 if (mCreated) { 84 LOG(WARNING) << getId() << " silence change requires destroyed"; 85 return -EBUSY; 86 } 87 88 mSilent = silent; 89 return OK; 90} 91 92status_t VolumeBase::setId(const std::string& id) { 93 if (mCreated) { 94 LOG(WARNING) << getId() << " id change requires not created"; 95 return -EBUSY; 96 } 97 98 mId = id; 99 return OK; 100} 101 102status_t VolumeBase::setPath(const std::string& path) { 103 if (mState != State::kChecking) { 104 LOG(WARNING) << getId() << " path change requires state checking"; 105 return -EBUSY; 106 } 107 108 mPath = path; 109 notifyEvent(ResponseCode::VolumePathChanged, mPath); 110 return OK; 111} 112 113status_t VolumeBase::setInternalPath(const std::string& internalPath) { 114 if (mState != State::kChecking) { 115 LOG(WARNING) << getId() << " internal path change requires state checking"; 116 return -EBUSY; 117 } 118 119 mInternalPath = internalPath; 120 notifyEvent(ResponseCode::VolumeInternalPathChanged, mInternalPath); 121 return OK; 122} 123 124void VolumeBase::notifyEvent(int event) { 125 if (mSilent) return; 126 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, 127 getId().c_str(), false); 128} 129 130void VolumeBase::notifyEvent(int event, const std::string& value) { 131 if (mSilent) return; 132 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, 133 StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false); 134} 135 136void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) { 137 mVolumes.push_back(volume); 138} 139 140void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) { 141 mVolumes.remove(volume); 142} 143 144std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) { 145 for (auto vol : mVolumes) { 146 if (vol->getId() == id) { 147 return vol; 148 } 149 } 150 return nullptr; 151} 152 153status_t VolumeBase::create() { 154 CHECK(!mCreated); 155 156 mCreated = true; 157 status_t res = doCreate(); 158 notifyEvent(ResponseCode::VolumeCreated, StringPrintf("%d %s", mType, mDiskId.c_str())); 159 setState(State::kUnmounted); 160 return res; 161} 162 163status_t VolumeBase::doCreate() { 164 return OK; 165} 166 167status_t VolumeBase::destroy() { 168 CHECK(mCreated); 169 170 if (mState == State::kMounted) { 171 unmount(); 172 setState(State::kBadRemoval); 173 } else { 174 setState(State::kRemoved); 175 } 176 177 notifyEvent(ResponseCode::VolumeDestroyed); 178 status_t res = doDestroy(); 179 mCreated = false; 180 return res; 181} 182 183status_t VolumeBase::doDestroy() { 184 return OK; 185} 186 187status_t VolumeBase::mount() { 188 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) { 189 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable"; 190 return -EBUSY; 191 } 192 193 setState(State::kChecking); 194 status_t res = doMount(); 195 if (res == OK) { 196 setState(State::kMounted); 197 } else { 198 setState(State::kUnmountable); 199 } 200 201 return res; 202} 203 204status_t VolumeBase::unmount() { 205 if (mState != State::kMounted) { 206 LOG(WARNING) << getId() << " unmount requires state mounted"; 207 return -EBUSY; 208 } 209 210 setState(State::kEjecting); 211 212 for (auto vol : mVolumes) { 213 if (vol->destroy()) { 214 LOG(WARNING) << getId() << " failed to destroy " << vol->getId() 215 << " stacked above"; 216 } 217 } 218 mVolumes.clear(); 219 220 status_t res = doUnmount(); 221 setState(State::kUnmounted); 222 return res; 223} 224 225status_t VolumeBase::format() { 226 if (mState == State::kMounted) { 227 unmount(); 228 } 229 230 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) { 231 LOG(WARNING) << getId() << " format requires state unmounted or unmountable"; 232 return -EBUSY; 233 } 234 235 setState(State::kFormatting); 236 status_t res = doFormat(); 237 setState(State::kUnmounted); 238 return res; 239} 240 241status_t VolumeBase::doFormat() { 242 return -ENOTSUP; 243} 244 245} // namespace vold 246} // namespace android 247