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