OSDN Git Service

Volumes know parent disks; unsupported disks.
authorJeff Sharkey <jsharkey@android.com>
Sat, 18 Apr 2015 00:35:20 +0000 (17:35 -0700)
committerJeff Sharkey <jsharkey@android.com>
Sat, 18 Apr 2015 00:43:56 +0000 (17:43 -0700)
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

CommandListener.cpp
Disk.cpp
PublicVolume.cpp
ResponseCode.h
VolumeBase.cpp
VolumeBase.h
VolumeManager.cpp
VolumeManager.h

index 813d831..fddee01 100644 (file)
@@ -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());
 
index 51eeba8..5e222b3 100644 (file)
--- a/Disk.cpp
+++ b/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;
index dc746cf..025d2eb 100644 (file)
@@ -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
index cdb4a79..2430f99 100644 (file)
@@ -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;
index 3b49b0d..2db5afe 100644 (file)
@@ -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;
+    }
+
+    mDiskId = diskId;
+    return OK;
+}
+
+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;
     }
 
-    mFlags = flags;
+    mMountFlags = mountFlags;
     return OK;
 }
 
-status_t VolumeBase::setUser(userid_t user) {
-    if (mState != State::kUnmounted) {
-        LOG(WARNING) << getId() << " user change requires state unmounted";
+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;
     }
 
-    mUser = user;
+    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()) {
index e7c7836..1010e94 100644 (file)
@@ -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 */
index dcadd14..bbafa42 100644 (file)
@@ -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"));
index 06d0ce3..44920e0 100644 (file)
@@ -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; }