diff options
author | San Mehat <san@google.com> | 2009-12-13 10:40:18 -0800 |
---|---|---|
committer | San Mehat <san@google.com> | 2009-12-19 09:54:42 -0800 |
commit | a2677e4ad01f250b0765f04adf0acfa6627efc98 (patch) | |
tree | 1b45710a1cf2fdad5350c42fb4d6295aa80e8134 /DirectVolume.cpp | |
parent | dd9b8e92aaf330b48ddb40a7380588ef92b53de6 (diff) | |
download | system_vold-a2677e4ad01f250b0765f04adf0acfa6627efc98.tar.gz system_vold-a2677e4ad01f250b0765f04adf0acfa6627efc98.tar.bz2 system_vold-a2677e4ad01f250b0765f04adf0acfa6627efc98.zip |
vold2: Get mounting/unmounting/formatting/sharing working
Signed-off-by: San Mehat <san@google.com>
Diffstat (limited to 'DirectVolume.cpp')
-rw-r--r-- | DirectVolume.cpp | 202 |
1 files changed, 161 insertions, 41 deletions
diff --git a/DirectVolume.cpp b/DirectVolume.cpp index cd12cf4..1fda955 100644 --- a/DirectVolume.cpp +++ b/DirectVolume.cpp @@ -19,20 +19,33 @@ #include <string.h> #include <errno.h> -#define LOG_TAG "Vold" +#include <linux/kdev_t.h> + +#define LOG_TAG "DirectVolume" #include <cutils/log.h> #include <sysutils/NetlinkEvent.h> #include "DirectVolume.h" +#include "VolumeManager.h" +#include "ResponseCode.h" + +// #define PARTITION_DEBUG -DirectVolume::DirectVolume(const char *label, const char *mount_point, int partIdx) : - Volume(label, mount_point) { +DirectVolume::DirectVolume(VolumeManager *vm, const char *label, + const char *mount_point, int partIdx) : + Volume(vm, label, mount_point) { mPartIdx = partIdx; - + mPaths = new PathCollection(); for (int i = 0; i < MAX_PARTITIONS; i++) mPartMinors[i] = -1; + mPendingPartMap = 0; + mDiskMajor = -1; + mDiskMinor = -1; + mDiskNumParts = 0; + + setState(Volume::State_NoMedia); } DirectVolume::~DirectVolume() { @@ -48,6 +61,18 @@ int DirectVolume::addPath(const char *path) { return 0; } +dev_t DirectVolume::getDiskDevice() { + return MKDEV(mDiskMajor, mDiskMinor); +} + +void DirectVolume::handleVolumeShared() { + setState(Volume::State_Shared); +} + +void DirectVolume::handleVolumeUnshared() { + setState(Volume::State_Idle); +} + int DirectVolume::handleBlockEvent(NetlinkEvent *evt) { const char *dp = evt->findParam("DEVPATH"); @@ -58,20 +83,37 @@ int DirectVolume::handleBlockEvent(NetlinkEvent *evt) { int action = evt->getAction(); const char *devtype = evt->findParam("DEVTYPE"); - if (!strcmp(devtype, "disk")) { - if (action == NetlinkEvent::NlActionAdd) + if (action == NetlinkEvent::NlActionAdd) { + int major = atoi(evt->findParam("MAJOR")); + int minor = atoi(evt->findParam("MINOR")); + char nodepath[255]; + + snprintf(nodepath, + sizeof(nodepath), "/dev/block/vold/%d:%d", + major, minor); + if (createDeviceNode(nodepath, major, minor)) { + LOGE("Error making device node '%s' (%s)", nodepath, + strerror(errno)); + } + if (!strcmp(devtype, "disk")) { handleDiskAdded(dp, evt); - else if (action == NetlinkEvent::NlActionRemove) - handleDiskRemoved(dp, evt); - else - LOGD("Ignoring non add/remove event"); - } else { - if (action == NetlinkEvent::NlActionAdd) + } else { handlePartitionAdded(dp, evt); - else if (action == NetlinkEvent::NlActionRemove) + } + } else if (action == NetlinkEvent::NlActionRemove) { + if (!strcmp(devtype, "disk")) { + handleDiskRemoved(dp, evt); + } else { handlePartitionRemoved(dp, evt); - else - LOGD("Ignoring non add/remove event"); + } + } else if (action == NetlinkEvent::NlActionChange) { + if (!strcmp(devtype, "disk")) { + handleDiskChanged(dp, evt); + } else { + handlePartitionChanged(dp, evt); + } + } else { + LOGW("Ignoring non add/remove/change event"); } return 0; @@ -83,8 +125,9 @@ int DirectVolume::handleBlockEvent(NetlinkEvent *evt) { void DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) { mDiskMajor = atoi(evt->findParam("MAJOR")); - mDiskMinor = atoi(evt->findParam("MAJOR")); + mDiskMinor = atoi(evt->findParam("MINOR")); mDiskNumParts = atoi(evt->findParam("NPARTS")); + char msg[255]; int partmask = 0; int i; @@ -94,13 +137,22 @@ void DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) { mPendingPartMap = partmask; if (mDiskNumParts == 0) { +#ifdef PARTITION_DEBUG LOGD("Dv::diskIns - No partitions - good to go son!"); +#endif setState(Volume::State_Idle); } else { +#ifdef PARTITION_DEBUG LOGD("Dv::diskIns - waiting for %d partitions (mask 0x%x)", mDiskNumParts, mPendingPartMap); +#endif setState(Volume::State_Pending); } + + snprintf(msg, sizeof(msg), "Volume %s %s disk inserted (%d:%d)", + getLabel(), getMountpoint(), mDiskMajor, mDiskMinor); + mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted, + msg, false); } void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { @@ -112,54 +164,122 @@ void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) LOGE("Partition '%s' has a different major than its disk!", devpath); return; } +#ifdef PARTITION_DEBUG + LOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor); +#endif mPartMinors[part_num -1] = minor; mPendingPartMap &= ~(1 << part_num); if (!mPendingPartMap) { +#ifdef PARTITION_DEBUG LOGD("Dv:partAdd: Got all partitions - ready to rock!"); +#endif setState(Volume::State_Idle); } else { +#ifdef PARTITION_DEBUG LOGD("Dv:partAdd: pending mask now = 0x%x", mPendingPartMap); +#endif + } +} + +void DirectVolume::handleDiskChanged(const char *devpath, NetlinkEvent *evt) { + int major = atoi(evt->findParam("MAJOR")); + int minor = atoi(evt->findParam("MINOR")); + + if ((major != mDiskMajor) || (minor != mDiskMinor)) { + return; + } + + LOGI("Volume %s disk has changed", getLabel()); + mDiskNumParts = atoi(evt->findParam("NPARTS")); + int partmask = 0; + int i; + for (i = 1; i <= mDiskNumParts; i++) { + partmask |= (1 << i); + } + mPendingPartMap = partmask; + + if (mDiskNumParts == 0) { + setState(Volume::State_Idle); + } else { + setState(Volume::State_Pending); } + +} + +void DirectVolume::handlePartitionChanged(const char *devpath, NetlinkEvent *evt) { } void DirectVolume::handleDiskRemoved(const char *devpath, NetlinkEvent *evt) { + int major = atoi(evt->findParam("MAJOR")); + int minor = atoi(evt->findParam("MINOR")); + char msg[255]; + + LOGD("Volume %s %s disk %d:%d removed\n", getLabel(), getMountpoint(), major, minor); + snprintf(msg, sizeof(msg), "Volume %s %s disk removed (%d:%d)", + getLabel(), getMountpoint(), major, minor); + mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskRemoved, + msg, false); + setState(Volume::State_NoMedia); } void DirectVolume::handlePartitionRemoved(const char *devpath, NetlinkEvent *evt) { + int major = atoi(evt->findParam("MAJOR")); + int minor = atoi(evt->findParam("MINOR")); + int part_num = atoi(evt->findParam("PARTN")); + char msg[255]; + + LOGD("Volume %s %s partition %d:%d removed\n", getLabel(), getMountpoint(), major, minor); + + /* + * The framework doesn't need to get notified of + * partition removal unless it's mounted. Otherwise + * the removal notification will be sent on the Disk + * itself + */ + if (getState() != Volume::State_Mounted) { + return; + } + + if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) { + /* + * Yikes, our mounted partition is going away! + */ + + snprintf(msg, sizeof(msg), "Volume %s %s bad removal (%d:%d)", + getLabel(), getMountpoint(), major, minor); + mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval, + msg, false); + if (Volume::unmountVol()) { + LOGE("Failed to unmount volume on bad removal (%s)", + strerror(errno)); + // XXX: At this point we're screwed for now + } else { + LOGD("Crisis averted"); + } + } } /* - * Called from Volume to determine the major/minor numbers - * to be used for mounting + * Called from base to get a list of devicenodes for mounting */ -int DirectVolume::prepareToMount(int *major, int *minor) { - *major = mDiskMajor; +int DirectVolume::getDeviceNodes(dev_t *devs, int max) { if (mPartIdx == -1) { - /* No specific partition specified */ - + // If the disk has no partitions, try the disk itself if (!mDiskNumParts) { - *minor = mDiskMinor; - return 0; + devs[0] = MKDEV(mDiskMajor, mDiskMinor); + return 1; } - /* - * XXX: Use first partition for now. - * The right thing to do would be to choose - * this based on the partition type. - * - */ - - *minor = mPartMinors[0]; - return 0; - } - - if (mPartIdx - 1 > mDiskNumParts) { - errno = EINVAL; - return -1; + int i; + for (i = 0; i < mDiskNumParts; i++) { + if (i == max) + break; + devs[i] = MKDEV(mDiskMajor, mPartMinors[i]); + } + return mDiskNumParts; } - - *minor = mPartMinors[mPartIdx-1]; - return 0; + devs[0] = MKDEV(mDiskMajor, mPartMinors[mPartIdx -1]); + return 1; } |