Volumes know parent disks; unsupported disks.
This is cleaner and more direct than the reverse of having the disk publish child volume membership. Rename state constants to match public API. Add state representing bad removal. Make it clear that volume flags are related to mounting. Send new unsupported disk event when we finish scanning an entire disk and have no meaningful volumes. Bug: 19993667 Change-Id: I08a91452ff561171a484d1da5745293ec893aec0
This commit is contained in:
parent
7d9d011865
commit
f1b996df6f
8 changed files with 84 additions and 57 deletions
|
@ -148,6 +148,9 @@ int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
|
|||
} else if (cmd == "shutdown") {
|
||||
return sendGenericOkFail(cli, vm->shutdown());
|
||||
|
||||
} else if (cmd == "debug") {
|
||||
return sendGenericOkFail(cli, vm->setDebug(true));
|
||||
|
||||
} else if (cmd == "partition" && argc > 3) {
|
||||
// partition [diskId] [public|private|mixed] [ratio]
|
||||
std::string id(argv[2]);
|
||||
|
@ -191,15 +194,15 @@ int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
|
|||
return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false);
|
||||
}
|
||||
|
||||
int flags = (argc > 3) ? atoi(argv[3]) : 0;
|
||||
userid_t user = (argc > 4) ? atoi(argv[4]) : -1;
|
||||
int mountFlags = (argc > 3) ? atoi(argv[3]) : 0;
|
||||
userid_t mountUserId = (argc > 4) ? atoi(argv[4]) : -1;
|
||||
|
||||
if (flags & android::vold::VolumeBase::Flags::kPrimary) {
|
||||
if (mountFlags & android::vold::VolumeBase::MountFlags::kPrimary) {
|
||||
vm->setPrimary(vol);
|
||||
}
|
||||
|
||||
vol->setFlags(flags);
|
||||
vol->setUser(user);
|
||||
vol->setMountFlags(mountFlags);
|
||||
vol->setMountUserId(mountUserId);
|
||||
|
||||
return sendGenericOkFail(cli, vol->mount());
|
||||
|
||||
|
|
15
Disk.cpp
15
Disk.cpp
|
@ -36,6 +36,8 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#define ENTIRE_DEVICE_FALLBACK 0
|
||||
|
||||
using android::base::ReadFileToString;
|
||||
using android::base::WriteStringToFile;
|
||||
using android::base::StringPrintf;
|
||||
|
@ -125,8 +127,8 @@ void Disk::createPublicVolume(dev_t device) {
|
|||
}
|
||||
|
||||
mVolumes.push_back(vol);
|
||||
vol->setDiskId(getId());
|
||||
vol->create();
|
||||
notifyEvent(ResponseCode::DiskVolumeCreated, vol->getId());
|
||||
}
|
||||
|
||||
void Disk::createPrivateVolume(dev_t device, const std::string& partGuid) {
|
||||
|
@ -157,14 +159,13 @@ void Disk::createPrivateVolume(dev_t device, const std::string& partGuid) {
|
|||
}
|
||||
|
||||
mVolumes.push_back(vol);
|
||||
vol->setDiskId(getId());
|
||||
vol->create();
|
||||
notifyEvent(ResponseCode::DiskVolumeCreated, vol->getId());
|
||||
}
|
||||
|
||||
void Disk::destroyAllVolumes() {
|
||||
for (auto vol : mVolumes) {
|
||||
vol->destroy();
|
||||
notifyEvent(ResponseCode::DiskVolumeDestroyed, vol->getId());
|
||||
}
|
||||
mVolumes.clear();
|
||||
}
|
||||
|
@ -295,11 +296,19 @@ status_t Disk::readPartitions() {
|
|||
}
|
||||
}
|
||||
|
||||
#if ENTIRE_DEVICE_FALLBACK
|
||||
// Ugly last ditch effort, treat entire disk as partition
|
||||
if (table == Table::kUnknown || !foundParts) {
|
||||
// TODO: use blkid to confirm filesystem before doing this
|
||||
LOG(WARNING) << mId << " has unknown partition table; trying entire device";
|
||||
createPublicVolume(mDevice);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Well this is embarrassing, we can't handle the disk
|
||||
if (mVolumes.size() == 0) {
|
||||
notifyEvent(ResponseCode::DiskUnsupported);
|
||||
}
|
||||
|
||||
mJustPartitioned = false;
|
||||
return OK;
|
||||
|
|
|
@ -124,18 +124,23 @@ status_t PublicVolume::doMount() {
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (getFlags() & Flags::kPrimary) {
|
||||
if (getMountFlags() & MountFlags::kPrimary) {
|
||||
initAsecStage();
|
||||
}
|
||||
|
||||
// Only need to spin up FUSE when visible
|
||||
if (!(getFlags() & Flags::kVisible)) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
// TODO: teach FUSE daemon to protect itself with user-specific GID
|
||||
if (!(mFusePid = fork())) {
|
||||
if (getFlags() & Flags::kPrimary) {
|
||||
if (!(getMountFlags() & MountFlags::kVisible)) {
|
||||
// TODO: mount so that only system apps can access
|
||||
if (execl(kFusePath, kFusePath,
|
||||
"-u", "1023", // AID_MEDIA_RW
|
||||
"-g", "1023", // AID_MEDIA_RW
|
||||
mRawPath.c_str(),
|
||||
mFusePath.c_str(),
|
||||
NULL)) {
|
||||
PLOG(ERROR) << "Failed to exec";
|
||||
}
|
||||
} else if (getMountFlags() & MountFlags::kPrimary) {
|
||||
if (execl(kFusePath, kFusePath,
|
||||
"-u", "1023", // AID_MEDIA_RW
|
||||
"-g", "1023", // AID_MEDIA_RW
|
||||
|
|
|
@ -69,8 +69,7 @@ public:
|
|||
static const int DiskCreated = 640;
|
||||
static const int DiskSizeChanged = 641;
|
||||
static const int DiskLabelChanged = 642;
|
||||
static const int DiskVolumeCreated = 643;
|
||||
static const int DiskVolumeDestroyed = 644;
|
||||
static const int DiskUnsupported = 643;
|
||||
static const int DiskDestroyed = 649;
|
||||
|
||||
static const int VolumeCreated = 650;
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace android {
|
|||
namespace vold {
|
||||
|
||||
VolumeBase::VolumeBase(Type type) :
|
||||
mType(type), mFlags(0), mUser(-1), mCreated(false), mState(
|
||||
mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState(
|
||||
State::kUnmounted), mSilent(false) {
|
||||
}
|
||||
|
||||
|
@ -49,23 +49,33 @@ void VolumeBase::setState(State state) {
|
|||
notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState));
|
||||
}
|
||||
|
||||
status_t VolumeBase::setFlags(int flags) {
|
||||
if (mState != State::kUnmounted) {
|
||||
LOG(WARNING) << getId() << " flags change requires state unmounted";
|
||||
status_t VolumeBase::setDiskId(const std::string& diskId) {
|
||||
if (mCreated) {
|
||||
LOG(WARNING) << getId() << " diskId change requires destroyed";
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
mFlags = flags;
|
||||
mDiskId = diskId;
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t VolumeBase::setUser(userid_t user) {
|
||||
if (mState != State::kUnmounted) {
|
||||
LOG(WARNING) << getId() << " user change requires state unmounted";
|
||||
status_t VolumeBase::setMountFlags(int mountFlags) {
|
||||
if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
|
||||
LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
mUser = user;
|
||||
mMountFlags = mountFlags;
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t VolumeBase::setMountUserId(userid_t mountUserId) {
|
||||
if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
|
||||
LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
mMountUserId = mountUserId;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -90,8 +100,8 @@ status_t VolumeBase::setId(const std::string& id) {
|
|||
}
|
||||
|
||||
status_t VolumeBase::setPath(const std::string& path) {
|
||||
if (mState != State::kMounting) {
|
||||
LOG(WARNING) << getId() << " path change requires state mounting";
|
||||
if (mState != State::kChecking) {
|
||||
LOG(WARNING) << getId() << " path change requires state checking";
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -134,7 +144,7 @@ status_t VolumeBase::create() {
|
|||
|
||||
mCreated = true;
|
||||
status_t res = doCreate();
|
||||
notifyEvent(ResponseCode::VolumeCreated, StringPrintf("%d", mType));
|
||||
notifyEvent(ResponseCode::VolumeCreated, StringPrintf("%d %s", mType, mDiskId.c_str()));
|
||||
setState(State::kUnmounted);
|
||||
return res;
|
||||
}
|
||||
|
@ -148,9 +158,11 @@ status_t VolumeBase::destroy() {
|
|||
|
||||
if (mState == State::kMounted) {
|
||||
unmount();
|
||||
setState(State::kBadRemoval);
|
||||
} else {
|
||||
setState(State::kRemoved);
|
||||
}
|
||||
|
||||
setState(State::kRemoved);
|
||||
notifyEvent(ResponseCode::VolumeDestroyed);
|
||||
status_t res = doDestroy();
|
||||
mCreated = false;
|
||||
|
@ -167,7 +179,7 @@ status_t VolumeBase::mount() {
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
setState(State::kMounting);
|
||||
setState(State::kChecking);
|
||||
status_t res = doMount();
|
||||
if (res == OK) {
|
||||
setState(State::kMounted);
|
||||
|
@ -184,7 +196,7 @@ status_t VolumeBase::unmount() {
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
setState(State::kUnmounting);
|
||||
setState(State::kEjecting);
|
||||
|
||||
for (auto vol : mVolumes) {
|
||||
if (vol->destroy()) {
|
||||
|
|
33
VolumeBase.h
33
VolumeBase.h
|
@ -55,7 +55,7 @@ public:
|
|||
kObb,
|
||||
};
|
||||
|
||||
enum Flags {
|
||||
enum MountFlags {
|
||||
/* Flag that volume is primary external storage */
|
||||
kPrimary = 1 << 0,
|
||||
/* Flag that volume is visible to normal apps */
|
||||
|
@ -63,31 +63,28 @@ public:
|
|||
};
|
||||
|
||||
enum class State {
|
||||
/* Next states: mounting, formatting */
|
||||
kUnmounted = 0,
|
||||
/* Next states: mounted, unmountable */
|
||||
kMounting,
|
||||
/* Next states: unmounting */
|
||||
kChecking,
|
||||
kMounted,
|
||||
/* Next states: unmounted */
|
||||
kMountedReadOnly,
|
||||
kFormatting,
|
||||
/* Next states: unmounted */
|
||||
kUnmounting,
|
||||
/* Next states: mounting, formatting */
|
||||
kEjecting,
|
||||
kUnmountable,
|
||||
/* Next states: none */
|
||||
kRemoved,
|
||||
kBadRemoval,
|
||||
};
|
||||
|
||||
const std::string& getId() { return mId; }
|
||||
const std::string& getDiskId() { return mDiskId; }
|
||||
Type getType() { return mType; }
|
||||
int getFlags() { return mFlags; }
|
||||
userid_t getUser() { return mUser; }
|
||||
int getMountFlags() { return mMountFlags; }
|
||||
userid_t getMountUserId() { return mMountUserId; }
|
||||
State getState() { return mState; }
|
||||
const std::string& getPath() { return mPath; }
|
||||
|
||||
status_t setFlags(int flags);
|
||||
status_t setUser(userid_t user);
|
||||
status_t setDiskId(const std::string& diskId);
|
||||
status_t setMountFlags(int mountFlags);
|
||||
status_t setMountUserId(userid_t mountUserId);
|
||||
status_t setSilent(bool silent);
|
||||
|
||||
void addVolume(const std::shared_ptr<VolumeBase>& volume);
|
||||
|
@ -119,12 +116,14 @@ protected:
|
|||
private:
|
||||
/* ID that uniquely references volume while alive */
|
||||
std::string mId;
|
||||
/* ID that uniquely references parent disk while alive */
|
||||
std::string mDiskId;
|
||||
/* Volume type */
|
||||
Type mType;
|
||||
/* Flags applicable to volume */
|
||||
int mFlags;
|
||||
/* Flags used when mounting this volume */
|
||||
int mMountFlags;
|
||||
/* User that owns this volume, otherwise -1 */
|
||||
userid_t mUser;
|
||||
userid_t mMountUserId;
|
||||
/* Flag indicating object is created */
|
||||
bool mCreated;
|
||||
/* Current state of volume */
|
||||
|
|
|
@ -59,8 +59,6 @@
|
|||
#include "VoldUtil.h"
|
||||
#include "cryptfs.h"
|
||||
|
||||
#define DEBUG_NETLINK 0
|
||||
|
||||
#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file"
|
||||
|
||||
#define ROUND_UP_POWER_OF_2(number, po2) (((!!(number & ((1U << po2) - 1))) << po2)\
|
||||
|
@ -248,8 +246,9 @@ char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
|
|||
return buffer;
|
||||
}
|
||||
|
||||
void VolumeManager::setDebug(bool enable) {
|
||||
int VolumeManager::setDebug(bool enable) {
|
||||
mDebug = enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VolumeManager::start() {
|
||||
|
@ -273,10 +272,11 @@ int VolumeManager::stop() {
|
|||
}
|
||||
|
||||
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
|
||||
#if DEBUG_NETLINK
|
||||
LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
|
||||
evt->dump();
|
||||
#endif
|
||||
if (mDebug) {
|
||||
LOG(VERBOSE) << "----------------";
|
||||
LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
|
||||
evt->dump();
|
||||
}
|
||||
|
||||
std::string eventPath(evt->findParam("DEVPATH"));
|
||||
std::string devType(evt->findParam("DEVTYPE"));
|
||||
|
|
|
@ -159,7 +159,7 @@ public:
|
|||
int unmountLoopImage(const char *containerId, const char *loopId,
|
||||
const char *fileName, const char *mountPoint, bool force);
|
||||
|
||||
void setDebug(bool enable);
|
||||
int setDebug(bool enable);
|
||||
|
||||
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
|
||||
SocketListener *getBroadcaster() { return mBroadcaster; }
|
||||
|
|
Loading…
Reference in a new issue