VolumeBase.cpp revision f1b996df6f8283aac6953b22bd9e2496d8c30c86
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 113void VolumeBase::notifyEvent(int event) { 114 if (mSilent) return; 115 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, 116 getId().c_str(), false); 117} 118 119void VolumeBase::notifyEvent(int event, const std::string& value) { 120 if (mSilent) return; 121 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, 122 StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false); 123} 124 125void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) { 126 mVolumes.push_back(volume); 127} 128 129void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) { 130 mVolumes.remove(volume); 131} 132 133std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) { 134 for (auto vol : mVolumes) { 135 if (vol->getId() == id) { 136 return vol; 137 } 138 } 139 return nullptr; 140} 141 142status_t VolumeBase::create() { 143 CHECK(!mCreated); 144 145 mCreated = true; 146 status_t res = doCreate(); 147 notifyEvent(ResponseCode::VolumeCreated, StringPrintf("%d %s", mType, mDiskId.c_str())); 148 setState(State::kUnmounted); 149 return res; 150} 151 152status_t VolumeBase::doCreate() { 153 return OK; 154} 155 156status_t VolumeBase::destroy() { 157 CHECK(mCreated); 158 159 if (mState == State::kMounted) { 160 unmount(); 161 setState(State::kBadRemoval); 162 } else { 163 setState(State::kRemoved); 164 } 165 166 notifyEvent(ResponseCode::VolumeDestroyed); 167 status_t res = doDestroy(); 168 mCreated = false; 169 return res; 170} 171 172status_t VolumeBase::doDestroy() { 173 return OK; 174} 175 176status_t VolumeBase::mount() { 177 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) { 178 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable"; 179 return -EBUSY; 180 } 181 182 setState(State::kChecking); 183 status_t res = doMount(); 184 if (res == OK) { 185 setState(State::kMounted); 186 } else { 187 setState(State::kUnmountable); 188 } 189 190 return res; 191} 192 193status_t VolumeBase::unmount() { 194 if (mState != State::kMounted) { 195 LOG(WARNING) << getId() << " unmount requires state mounted"; 196 return -EBUSY; 197 } 198 199 setState(State::kEjecting); 200 201 for (auto vol : mVolumes) { 202 if (vol->destroy()) { 203 LOG(WARNING) << getId() << " failed to destroy " << vol->getId() 204 << " stacked above"; 205 } 206 } 207 mVolumes.clear(); 208 209 status_t res = doUnmount(); 210 setState(State::kUnmounted); 211 return res; 212} 213 214status_t VolumeBase::format() { 215 if (mState == State::kMounted) { 216 unmount(); 217 } 218 219 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) { 220 LOG(WARNING) << getId() << " format requires state unmounted or unmountable"; 221 return -EBUSY; 222 } 223 224 setState(State::kFormatting); 225 status_t res = doFormat(); 226 setState(State::kUnmounted); 227 return res; 228} 229 230status_t VolumeBase::doFormat() { 231 return -ENOTSUP; 232} 233 234} // namespace vold 235} // namespace android 236