blob: 2590ecf08fe2ea8bf1652383a1957f1457795434 [file] [log] [blame]
Jeff Sharkeydeb24052015-03-02 21:01:40 -08001/*
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
Jeff Sharkeydeb24052015-03-02 21:01:40 -080017#include "Utils.h"
18#include "VolumeBase.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070019#include "VolumeManager.h"
20#include "ResponseCode.h"
Jeff Sharkeydeb24052015-03-02 21:01:40 -080021
Jeff Sharkey36801cc2015-03-13 16:09:20 -070022#include <base/stringprintf.h>
23#include <base/logging.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080024
25#include <fcntl.h>
26#include <stdlib.h>
27#include <sys/mount.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30
Jeff Sharkey36801cc2015-03-13 16:09:20 -070031using android::base::StringPrintf;
32
33#define DEBUG 1
34
Jeff Sharkeydeb24052015-03-02 21:01:40 -080035namespace android {
36namespace vold {
37
Jeff Sharkey36801cc2015-03-13 16:09:20 -070038VolumeBase::VolumeBase(Type type) :
39 mType(type), mFlags(0), mUser(-1), mCreated(false), mState(State::kUnmounted) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -080040}
41
42VolumeBase::~VolumeBase() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -070043 CHECK(!mCreated);
Jeff Sharkeydeb24052015-03-02 21:01:40 -080044}
45
Jeff Sharkey36801cc2015-03-13 16:09:20 -070046void VolumeBase::setState(State state) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -080047 mState = state;
48
Jeff Sharkey36801cc2015-03-13 16:09:20 -070049 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
50 ResponseCode::VolumeStateChanged,
51 StringPrintf("%s %d", getId().c_str(), mState).c_str(), false);
Jeff Sharkeydeb24052015-03-02 21:01:40 -080052}
53
Jeff Sharkey36801cc2015-03-13 16:09:20 -070054status_t VolumeBase::setFlags(int flags) {
55 if (mState != State::kUnmounted) {
56 LOG(WARNING) << getId() << " flags change requires state unmounted";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080057 return -EBUSY;
58 }
59
Jeff Sharkey36801cc2015-03-13 16:09:20 -070060 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);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700116
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700117 mCreated = true;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700118 status_t res = doCreate();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700119 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
120 ResponseCode::VolumeCreated,
121 StringPrintf("%s %d", getId().c_str(), mType).c_str(), false);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700122 return res;
123}
124
125status_t VolumeBase::doCreate() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700126 return OK;
127}
128
129status_t VolumeBase::destroy() {
130 CHECK(mCreated);
131
132 if (mState == State::kMounted) {
133 unmount();
134 }
135
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700136 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
137 ResponseCode::VolumeDestroyed, getId().c_str(), false);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700138 status_t res = doDestroy();
139 mCreated = false;
140 return res;
141}
142
143status_t VolumeBase::doDestroy() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700144 return OK;
145}
146
147status_t VolumeBase::mount() {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700148 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
149 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700150 return -EBUSY;
151 }
152
153 setState(State::kMounting);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800154 status_t res = doMount();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700155 if (res == OK) {
156 setState(State::kMounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800157 } else {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700158 setState(State::kUnmountable);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800159 }
160
161 return res;
162}
163
164status_t VolumeBase::unmount() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700165 if (mState != State::kMounted) {
166 LOG(WARNING) << getId() << " unmount requires state mounted";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800167 return -EBUSY;
168 }
169
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700170 setState(State::kUnmounting);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800171
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700172 for (auto vol : mVolumes) {
173 if (vol->unmount()) {
174 LOG(WARNING) << getId() << " failed to unmount " << vol->getId()
175 << " stacked above";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800176 }
177 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700178 mVolumes.clear();
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800179
180 status_t res = doUnmount();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700181 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800182 return res;
183}
184
185status_t VolumeBase::format() {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700186 if (mState == State::kMounted) {
187 unmount();
188 }
189
190 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
191 LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800192 return -EBUSY;
193 }
194
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700195 setState(State::kFormatting);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800196 status_t res = doFormat();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700197 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800198 return res;
199}
200
201status_t VolumeBase::doFormat() {
202 return -ENOTSUP;
203}
204
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800205} // namespace vold
206} // namespace android