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