DirectVolume.cpp revision 507d31b86b38dffe7c60ca5c54b5e631f5a7cab3
1f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat/* 2f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Copyright (C) 2008 The Android Open Source Project 3f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * 4f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * you may not use this file except in compliance with the License. 6f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * You may obtain a copy of the License at 7f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * 8f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * 10f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Unless required by applicable law or agreed to in writing, software 11f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * See the License for the specific language governing permissions and 14f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * limitations under the License. 15f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat */ 16f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 17f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdio.h> 18fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <stdlib.h> 19f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <string.h> 20fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <errno.h> 21f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 22a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <linux/kdev_t.h> 23a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 24a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#define LOG_TAG "DirectVolume" 25f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 26f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h> 27fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <sysutils/NetlinkEvent.h> 28f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 29ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat#include "DirectVolume.h" 30a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "VolumeManager.h" 31a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h" 3229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h" 33a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 34a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat// #define PARTITION_DEBUG 35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 36a2677e4ad01f250b0765f04adf0acfa6627efc98San MehatDirectVolume::DirectVolume(VolumeManager *vm, const char *label, 37a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat const char *mount_point, int partIdx) : 38a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat Volume(vm, label, mount_point) { 39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mPartIdx = partIdx; 40a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mPaths = new PathCollection(); 42dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat for (int i = 0; i < MAX_PARTITIONS; i++) 43dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat mPartMinors[i] = -1; 44a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mPendingPartMap = 0; 45a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mDiskMajor = -1; 46a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mDiskMinor = -1; 47a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mDiskNumParts = 0; 48a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 49a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_NoMedia); 50f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 52ae10b91044bf76b40b77d81c169e48e0bbdf6d75San MehatDirectVolume::~DirectVolume() { 53f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat PathCollection::iterator it; 54f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 55f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat for (it = mPaths->begin(); it != mPaths->end(); ++it) 56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat free(*it); 57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat delete mPaths; 58f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 60ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehatint DirectVolume::addPath(const char *path) { 61f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mPaths->push_back(strdup(path)); 62f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return 0; 63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 6529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallvoid DirectVolume::setFlags(int flags) { 6629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall mFlags = flags; 6729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall} 6829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 69a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatdev_t DirectVolume::getDiskDevice() { 70a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return MKDEV(mDiskMajor, mDiskMinor); 71a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 72a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 732dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwooddev_t DirectVolume::getShareDevice() { 742dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood if (mPartIdx != -1) { 752dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood return MKDEV(mDiskMajor, mPartIdx); 762dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood } else { 772dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood return MKDEV(mDiskMajor, mDiskMinor); 782dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood } 792dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood} 802dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood 81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid DirectVolume::handleVolumeShared() { 82a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Shared); 83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid DirectVolume::handleVolumeUnshared() { 86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Idle); 87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 89ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehatint DirectVolume::handleBlockEvent(NetlinkEvent *evt) { 90fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat const char *dp = evt->findParam("DEVPATH"); 91f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 92fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat PathCollection::iterator it; 93f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat for (it = mPaths->begin(); it != mPaths->end(); ++it) { 94f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat if (!strncmp(dp, *it, strlen(*it))) { 95fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat /* We can handle this disk */ 96fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat int action = evt->getAction(); 97fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat const char *devtype = evt->findParam("DEVTYPE"); 98fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 99a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (action == NetlinkEvent::NlActionAdd) { 100a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int major = atoi(evt->findParam("MAJOR")); 101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int minor = atoi(evt->findParam("MINOR")); 102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char nodepath[255]; 103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat snprintf(nodepath, 105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat sizeof(nodepath), "/dev/block/vold/%d:%d", 106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat major, minor); 107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (createDeviceNode(nodepath, major, minor)) { 10897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Error making device node '%s' (%s)", nodepath, 109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat strerror(errno)); 110a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!strcmp(devtype, "disk")) { 112fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat handleDiskAdded(dp, evt); 113a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else { 114fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat handlePartitionAdded(dp, evt); 115a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 116a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else if (action == NetlinkEvent::NlActionRemove) { 117a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!strcmp(devtype, "disk")) { 118a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat handleDiskRemoved(dp, evt); 119a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else { 120fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat handlePartitionRemoved(dp, evt); 121a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 122a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else if (action == NetlinkEvent::NlActionChange) { 123a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!strcmp(devtype, "disk")) { 124a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat handleDiskChanged(dp, evt); 125a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else { 126a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat handlePartitionChanged(dp, evt); 127a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 128a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else { 12997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Ignoring non add/remove/change event"); 130f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 131fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 132f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return 0; 133f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 134f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 135f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat errno = ENODEV; 136f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return -1; 137f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 138fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 139ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehatvoid DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) { 140da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root mDiskMajor = atoi(evt->findParam("MAJOR")); 141da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root mDiskMinor = atoi(evt->findParam("MINOR")); 1427b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat 1437b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat const char *tmp = evt->findParam("NPARTS"); 1447b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat if (tmp) { 1457b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat mDiskNumParts = atoi(tmp); 1467b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat } else { 14797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Kernel block uevent missing 'NPARTS'"); 1487b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat mDiskNumParts = 1; 1497b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat } 1507b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat 151a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char msg[255]; 152fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 153fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat int partmask = 0; 154fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat int i; 15559abc3c56b432089abfe868c04cdbc3b6d28aee2San Mehat for (i = 1; i <= mDiskNumParts; i++) { 156fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat partmask |= (1 << i); 157fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat } 158fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat mPendingPartMap = partmask; 159fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 160fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat if (mDiskNumParts == 0) { 161a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef PARTITION_DEBUG 16297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Dv::diskIns - No partitions - good to go son!"); 163a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif 164fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat setState(Volume::State_Idle); 165fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat } else { 166a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef PARTITION_DEBUG 16797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Dv::diskIns - waiting for %d partitions (mask 0x%x)", 168fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat mDiskNumParts, mPendingPartMap); 169a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif 170fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat setState(Volume::State_Pending); 171fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat } 172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 173a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat snprintf(msg, sizeof(msg), "Volume %s %s disk inserted (%d:%d)", 174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat getLabel(), getMountpoint(), mDiskMajor, mDiskMinor); 175a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted, 176a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat msg, false); 177fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat} 178fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 179ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehatvoid DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { 180da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int major = atoi(evt->findParam("MAJOR")); 181da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int minor = atoi(evt->findParam("MINOR")); 1827b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat 1837b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat int part_num; 1847b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat 1857b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat const char *tmp = evt->findParam("PARTN"); 1867b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat 1877b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat if (tmp) { 1887b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat part_num = atoi(tmp); 1897b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat } else { 19097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Kernel block uevent missing 'PARTN'"); 1917b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat part_num = 1; 1927b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat } 19359abc3c56b432089abfe868c04cdbc3b6d28aee2San Mehat 194f3d3ce5e53ab7928f4c292c183c417a1bd051151Nick Kralevich if (part_num > MAX_PARTITIONS || part_num < 1) { 195cc8e96c8dccea1e8041db3146d389175582d3890Nick Kralevich SLOGE("Invalid 'PARTN' value"); 196cc8e96c8dccea1e8041db3146d389175582d3890Nick Kralevich return; 197f3d3ce5e53ab7928f4c292c183c417a1bd051151Nick Kralevich } 198f3d3ce5e53ab7928f4c292c183c417a1bd051151Nick Kralevich 1992a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat if (part_num > mDiskNumParts) { 2002a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat mDiskNumParts = part_num; 2012a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat } 2022a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat 203dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat if (major != mDiskMajor) { 20497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Partition '%s' has a different major than its disk!", devpath); 205dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat return; 206dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat } 207a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef PARTITION_DEBUG 20897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor); 209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif 210def8f3168305cc57803f1e9aafd8ed6d8e93067dChih-Wei Huang if (part_num > MAX_PARTITIONS) { 211def8f3168305cc57803f1e9aafd8ed6d8e93067dChih-Wei Huang SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS); 212d766090b7a72562be9e64700e13882663004650eBruce Beare } else { 213d766090b7a72562be9e64700e13882663004650eBruce Beare mPartMinors[part_num -1] = minor; 214d766090b7a72562be9e64700e13882663004650eBruce Beare } 21559abc3c56b432089abfe868c04cdbc3b6d28aee2San Mehat mPendingPartMap &= ~(1 << part_num); 216d766090b7a72562be9e64700e13882663004650eBruce Beare 21759abc3c56b432089abfe868c04cdbc3b6d28aee2San Mehat if (!mPendingPartMap) { 218a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef PARTITION_DEBUG 21997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Dv:partAdd: Got all partitions - ready to rock!"); 220a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif 2212a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat if (getState() != Volume::State_Formatting) { 2222a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat setState(Volume::State_Idle); 223507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer if (mRetryMount == true) { 224507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer mRetryMount = false; 225507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer mountVol(); 226507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer } 2272a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat } 22859abc3c56b432089abfe868c04cdbc3b6d28aee2San Mehat } else { 229a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef PARTITION_DEBUG 23097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Dv:partAdd: pending mask now = 0x%x", mPendingPartMap); 231a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif 232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 233a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 234a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 235a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid DirectVolume::handleDiskChanged(const char *devpath, NetlinkEvent *evt) { 236da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int major = atoi(evt->findParam("MAJOR")); 237da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int minor = atoi(evt->findParam("MINOR")); 238a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 239a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if ((major != mDiskMajor) || (minor != mDiskMinor)) { 240a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return; 241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 242a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 24397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGI("Volume %s disk has changed", getLabel()); 2447b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat const char *tmp = evt->findParam("NPARTS"); 2457b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat if (tmp) { 2467b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat mDiskNumParts = atoi(tmp); 2477b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat } else { 24897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Kernel block uevent missing 'NPARTS'"); 2497b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat mDiskNumParts = 1; 2507b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat } 2517b8f2db4b07deaaa2f6f5ffbee0386a394032b08San Mehat 252a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int partmask = 0; 253a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int i; 254a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat for (i = 1; i <= mDiskNumParts; i++) { 255a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat partmask |= (1 << i); 256a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mPendingPartMap = partmask; 258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 2592a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat if (getState() != Volume::State_Formatting) { 2602a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat if (mDiskNumParts == 0) { 2612a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat setState(Volume::State_Idle); 2622a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat } else { 2632a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat setState(Volume::State_Pending); 2642a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat } 26559abc3c56b432089abfe868c04cdbc3b6d28aee2San Mehat } 266a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 267a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 268a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid DirectVolume::handlePartitionChanged(const char *devpath, NetlinkEvent *evt) { 269da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int major = atoi(evt->findParam("MAJOR")); 270da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int minor = atoi(evt->findParam("MINOR")); 27197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Volume %s %s partition %d:%d changed\n", getLabel(), getMountpoint(), major, minor); 272fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat} 273fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 274ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehatvoid DirectVolume::handleDiskRemoved(const char *devpath, NetlinkEvent *evt) { 275da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int major = atoi(evt->findParam("MAJOR")); 276da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int minor = atoi(evt->findParam("MINOR")); 277a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char msg[255]; 278a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 27997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Volume %s %s disk %d:%d removed\n", getLabel(), getMountpoint(), major, minor); 280a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat snprintf(msg, sizeof(msg), "Volume %s %s disk removed (%d:%d)", 281a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat getLabel(), getMountpoint(), major, minor); 282a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskRemoved, 283a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat msg, false); 284a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_NoMedia); 285fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat} 286fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat 287ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehatvoid DirectVolume::handlePartitionRemoved(const char *devpath, NetlinkEvent *evt) { 288da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int major = atoi(evt->findParam("MAJOR")); 289da62e7c00259f6b98696cedb7d031f04951caef0Kenny Root int minor = atoi(evt->findParam("MINOR")); 290a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char msg[255]; 29175a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan int state; 292a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 29397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Volume %s %s partition %d:%d removed\n", getLabel(), getMountpoint(), major, minor); 294a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 295a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat /* 296a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * The framework doesn't need to get notified of 297a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * partition removal unless it's mounted. Otherwise 298a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * the removal notification will be sent on the Disk 299a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * itself 300a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */ 30175a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan state = getState(); 30275a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan if (state != Volume::State_Mounted && state != Volume::State_Shared) { 303a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return; 304a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 305a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 306a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) { 307a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat /* 308a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Yikes, our mounted partition is going away! 309a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */ 310a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 311a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat snprintf(msg, sizeof(msg), "Volume %s %s bad removal (%d:%d)", 312a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat getLabel(), getMountpoint(), major, minor); 313a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval, 314a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat msg, false); 3151a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat 3161a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat if (mVm->cleanupAsec(this, true)) { 3171a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat SLOGE("Failed to cleanup ASEC - unmount will probably fail!"); 3181a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat } 3191a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat 3204ba8948dc16463053e21cda5744f519a555080d0San Mehat if (Volume::unmountVol(true)) { 32197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Failed to unmount volume on bad removal (%s)", 322a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat strerror(errno)); 323a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat // XXX: At this point we're screwed for now 324a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else { 32597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Crisis averted"); 326a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 32775a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan } else if (state == Volume::State_Shared) { 32875a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan /* removed during mass storage */ 32975a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan snprintf(msg, sizeof(msg), "Volume %s bad removal (%d:%d)", 33075a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan getLabel(), major, minor); 33175a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval, 33275a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan msg, false); 33375a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan 33475a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan if (mVm->unshareVolume(getLabel(), "ums")) { 33575a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan SLOGE("Failed to unshare volume on bad removal (%s)", 33675a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan strerror(errno)); 33775a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan } else { 33875a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan SLOGD("Crisis averted"); 33975a3e1a95af0a2790de1b12aeca0008bfdc61649Ethan } 340a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 341fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat} 34249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 343dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat/* 344a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Called from base to get a list of devicenodes for mounting 345dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat */ 346a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint DirectVolume::getDeviceNodes(dev_t *devs, int max) { 347dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 348dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat if (mPartIdx == -1) { 349a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat // If the disk has no partitions, try the disk itself 350dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat if (!mDiskNumParts) { 351a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat devs[0] = MKDEV(mDiskMajor, mDiskMinor); 352a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 1; 353dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat } 354dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 355a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int i; 356a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat for (i = 0; i < mDiskNumParts; i++) { 357a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (i == max) 358a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat break; 359a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat devs[i] = MKDEV(mDiskMajor, mPartMinors[i]); 360a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 361a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return mDiskNumParts; 362dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat } 363a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat devs[0] = MKDEV(mDiskMajor, mPartMinors[mPartIdx -1]); 364a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 1; 36549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat} 36629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 36729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall/* 36829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * Called from base to update device info, 36929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * e.g. When setting up an dm-crypt mapping for the sd card. 37029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall */ 37129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallint DirectVolume::updateDeviceInfo(char *new_path, int new_major, int new_minor) 37229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall{ 37329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall PathCollection::iterator it; 37429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 37529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if (mPartIdx == -1) { 37629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall SLOGE("Can only change device info on a partition\n"); 37729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return -1; 37829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 37929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 38029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall /* 38129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * This is to change the sysfs path associated with a partition, in particular, 38229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * for an internal SD card partition that is encrypted. Thus, the list is 38329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * expected to be only 1 entry long. Check that and bail if not. 38429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall */ 38529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if (mPaths->size() != 1) { 38629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall SLOGE("Cannot change path if there are more than one for a volume\n"); 38729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return -1; 38829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 38929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 39029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall it = mPaths->begin(); 39129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall free(*it); /* Free the string storage */ 39229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall mPaths->erase(it); /* Remove it from the list */ 39329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall addPath(new_path); /* Put the new path on the list */ 39429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 39529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall mDiskMajor = new_major; 39629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall mDiskMinor = new_minor; 39729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall /* Ugh, virual block devices don't use minor 0 for whole disk and minor > 0 for 39829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * partition number. They don't have partitions, they are just virtual block 39929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * devices, and minor number 0 is the first dm-crypt device. Luckily the first 40029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * dm-crypt device is for the userdata partition, which gets minor number 0, and 40129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * it is not managed by vold. So the next device is minor number one, which we 40229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * will call partition one. 40329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall */ 40429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall mPartIdx = new_minor; 40529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall mPartMinors[new_minor-1] = new_minor; 40629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 40729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall mIsDecrypted = 1; 40829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 40929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return 0; 41029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall} 41129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 41229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall/* 41329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * Called from base to give cryptfs all the info it needs to encrypt eligible volumes 41429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall */ 41529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallint DirectVolume::getVolInfo(struct volume_info *v) 41629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall{ 41729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall strcpy(v->label, mLabel); 41829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall strcpy(v->mnt_point, mMountpoint); 41929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall v->flags=mFlags; 42029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall /* Other fields of struct volume_info are filled in by the caller or cryptfs.c */ 42129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 42229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return 0; 42329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall} 424