Devmapper.cpp revision 0586d54053ee00e6d6523d4f125282ccb9a24aab
1b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat/* 2b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Copyright (C) 2008 The Android Open Source Project 3b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * 4b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * you may not use this file except in compliance with the License. 6b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * You may obtain a copy of the License at 7b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * 8b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * 10b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Unless required by applicable law or agreed to in writing, software 11b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * See the License for the specific language governing permissions and 14b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * limitations under the License. 15b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat */ 16b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 17b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <stdio.h> 18b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <fcntl.h> 19b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <unistd.h> 20b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <errno.h> 21b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <string.h> 22b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 23b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <sys/types.h> 24b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <sys/ioctl.h> 25b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <sys/stat.h> 26b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 27b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#define LOG_TAG "Vold" 28b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 29b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <cutils/log.h> 30b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 31b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include "Devmapper.h" 32b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 33b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatvoid Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize, 34b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat const char *name, unsigned flags) { 35b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat memset(io, 0, dataSize); 36b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat io->data_size = dataSize; 37b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat io->data_start = sizeof(struct dm_ioctl); 38b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat io->version[0] = 4; 39b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat io->version[1] = 0; 40b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat io->version[2] = 0; 41b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat io->flags = flags; 42b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat strncpy(io->name, name, sizeof(io->name)); 43b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 44b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 45b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatint Devmapper::lookupActive(const char *name, char *ubuffer, size_t len) { 46b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char *buffer = (char *) malloc(4096); 47b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (!buffer) { 48b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error allocating memory (%s)", strerror(errno)); 49b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 50b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 51b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 52b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat int fd; 53b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 54b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error opening devmapper (%s)", strerror(errno)); 55b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 56b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 57b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 58b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 59b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat struct dm_ioctl *io = (struct dm_ioctl *) buffer; 60b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 61b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat ioctlInit(io, 4096, name, 0); 62b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (ioctl(fd, DM_DEV_STATUS, io)) { 638b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat if (errno != ENXIO) { 648b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat LOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno)); 65b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 66b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 67b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 68b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 69b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 70b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 71b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 72b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); 73b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 74b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGD("Newly created devmapper instance minor = %d\n", minor); 75b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat snprintf(ubuffer, len, "/dev/block/dm-%u", minor); 76b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return 0; 77b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 78b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 798b8f71b1d760411279f3b07a5c97709f052c689eSan Mehatint Devmapper::create(const char *name, const char *loopFile, const char *key, 808b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat unsigned int numSectors, char *ubuffer, size_t len) { 81b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char *buffer = (char *) malloc(4096); 82b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (!buffer) { 83b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error allocating memory (%s)", strerror(errno)); 84b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 85b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 86b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 87b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat int fd; 88b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 89b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error opening devmapper (%s)", strerror(errno)); 90b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 91b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 92b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 93b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 94b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat struct dm_ioctl *io = (struct dm_ioctl *) buffer; 95b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 96b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // Create the DM device 97b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat ioctlInit(io, 4096, name, 0); 98b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 99b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (ioctl(fd, DM_DEV_CREATE, io)) { 100b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error creating device mapping (%s)", strerror(errno)); 101b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 102b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 103b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 104b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 105b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 106b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // Set the legacy geometry 107b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat ioctlInit(io, 4096, name, 0); 108b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 109b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char *geoParams = buffer + sizeof(struct dm_ioctl); 110b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // bps=512 spc=8 res=32 nft=2 sec=8190 mid=0xf0 spt=63 hds=64 hid=0 bspf=8 rdcl=2 infs=1 bkbs=2 111b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat strcpy(geoParams, "0 64 63 0"); 112b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat geoParams += strlen(geoParams) + 1; 113b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat geoParams = (char *) _align(geoParams, 8); 114b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) { 115b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error setting device geometry (%s)", strerror(errno)); 116b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 117b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 118b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 119b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 120b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 121b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // Retrieve the device number we were allocated 122b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat ioctlInit(io, 4096, name, 0); 123b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (ioctl(fd, DM_DEV_STATUS, io)) { 1248b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat LOGE("Error retrieving devmapper status (%s)", strerror(errno)); 125b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 126b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 127b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 128b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 129b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 130b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); 131b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGD("Newly created devmapper instance minor = %d\n", minor); 132b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat snprintf(ubuffer, len, "/dev/block/dm-%u", minor); 133b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 134b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // Load the table 135b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat struct dm_target_spec *tgt; 136b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; 137b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 138b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat ioctlInit(io, 4096, name, DM_STATUS_TABLE_FLAG); 139b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat io->target_count = 1; 140b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat tgt->status = 0; 141b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat tgt->sector_start = 0; 1428b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat tgt->length = numSectors; 143b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat strcpy(tgt->target_type, "crypt"); 144b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 145b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char *cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 146b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat sprintf(cryptParams, "twofish %s 0 %s 0", key, loopFile); 147b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat cryptParams += strlen(cryptParams) + 1; 148b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat cryptParams = (char *) _align(cryptParams, 8); 149b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat tgt->next = cryptParams - buffer; 150b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 151b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (ioctl(fd, DM_TABLE_LOAD, io)) { 152b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error loading mapping table (%s)", strerror(errno)); 153b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 154b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 155b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 156b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 157b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 158b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // Resume the new table 159b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat ioctlInit(io, 4096, name, 0); 160b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 161b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (ioctl(fd, DM_DEV_SUSPEND, io)) { 162b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error Resuming (%s)", strerror(errno)); 163b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 164b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 165b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 166b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 167b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 168b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 169b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 170b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return 0; 171b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 172b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 173b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatint Devmapper::destroy(const char *name) { 174b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat char *buffer = (char *) malloc(4096); 175b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (!buffer) { 176b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error allocating memory (%s)", strerror(errno)); 177b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 178b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 179b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 180b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat int fd; 181b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 182b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat LOGE("Error opening devmapper (%s)", strerror(errno)); 183b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 184b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 185b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 186b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 187b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat struct dm_ioctl *io = (struct dm_ioctl *) buffer; 188b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 189b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // Create the DM device 190b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat ioctlInit(io, 4096, name, 0); 191b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 192b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (ioctl(fd, DM_DEV_REMOVE, io)) { 1930586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat if (errno != ENXIO) { 1940586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat LOGE("Error destroying device mapping (%s)", strerror(errno)); 1950586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat } 196b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 197b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 198b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return -1; 199b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 200b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 201b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat free(buffer); 202b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat close(fd); 203b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return 0; 204b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 205b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 206b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatvoid *Devmapper::_align(void *ptr, unsigned int a) 207b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{ 208b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat register unsigned long agn = --a; 209b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 210b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat return (void *) (((unsigned long) ptr + agn) & ~agn); 211b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 212b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 213