OSDN Git Service

Merge "Checkpoint of better dynamic device support."
[android-x86/system-vold.git] / VolumeBase.cpp
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 #define LOG_TAG "Vold"
18
19 #include "Utils.h"
20 #include "VolumeBase.h"
21
22 #include <cutils/log.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 namespace android {
31 namespace vold {
32
33 VolumeBase::VolumeBase(VolumeType type) :
34         mType(type), mState(VolumeState::kUnmounted) {
35 }
36
37 VolumeBase::~VolumeBase() {
38 }
39
40 void VolumeBase::setState(VolumeState state) {
41     mState = state;
42
43     // TODO: publish state up to framework
44 }
45
46 void VolumeBase::stackVolume(const std::shared_ptr<VolumeBase>& volume) {
47     mStacked.push_back(volume);
48 }
49
50 void VolumeBase::unstackVolume(const std::shared_ptr<VolumeBase>& volume) {
51     mStacked.remove(volume);
52 }
53
54 status_t VolumeBase::mount() {
55     if (getState() != VolumeState::kUnmounted) {
56         SLOGE("Must be unmounted to mount %s", getId().c_str());
57         return -EBUSY;
58     }
59
60     setState(VolumeState::kMounting);
61     status_t res = doMount();
62     if (!res) {
63         setState(VolumeState::kMounted);
64     } else {
65         setState(VolumeState::kCorrupt);
66     }
67
68     return res;
69 }
70
71 status_t VolumeBase::unmount() {
72     if (getState() != VolumeState::kMounted) {
73         SLOGE("Must be mounted to unmount %s", getId().c_str());
74         return -EBUSY;
75     }
76
77     setState(VolumeState::kUnmounting);
78
79     for (std::string target : mBindTargets) {
80         ForceUnmount(target);
81     }
82     mBindTargets.clear();
83
84     for (std::shared_ptr<VolumeBase> v : mStacked) {
85         if (v->unmount()) {
86             ALOGW("Failed to unmount %s stacked above %s", v->getId().c_str(),
87                     getId().c_str());
88         }
89     }
90     mStacked.clear();
91
92     status_t res = doUnmount();
93     setState(VolumeState::kUnmounted);
94     return res;
95 }
96
97 status_t VolumeBase::format() {
98     if (getState() != VolumeState::kUnmounted
99             || getState() != VolumeState::kCorrupt) {
100         SLOGE("Must be unmounted or corrupt to format %s", getId().c_str());
101         return -EBUSY;
102     }
103
104     setState(VolumeState::kFormatting);
105     status_t res = doFormat();
106     setState(VolumeState::kUnmounted);
107     return res;
108 }
109
110 status_t VolumeBase::doFormat() {
111     return -ENOTSUP;
112 }
113
114 status_t VolumeBase::mountBind(const std::string& source, const std::string& target) {
115     if (::mount(source.c_str(), target.c_str(), "", MS_BIND, NULL)) {
116         SLOGE("Failed to bind mount %s to %s: %s", source.c_str(),
117                 target.c_str(), strerror(errno));
118         return -errno;
119     }
120     mBindTargets.push_back(target);
121     return OK;
122 }
123
124 status_t VolumeBase::unmountBind(const std::string& target) {
125     ForceUnmount(target);
126     mBindTargets.remove(target);
127     return OK;
128 }
129
130 }  // namespace vold
131 }  // namespace android