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