blob: 4d94e7b2fb8e87c045287a1e365563dc0336f810 [file] [log] [blame]
San Mehatb78a32c2010-01-10 13:02:12 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <fcntl.h>
19#include <unistd.h>
20#include <errno.h>
21#include <string.h>
Peter Bohm092aa1c2011-04-01 12:35:25 +020022#include <stdlib.h>
San Mehatb78a32c2010-01-10 13:02:12 -080023
24#include <sys/types.h>
25#include <sys/ioctl.h>
26#include <sys/stat.h>
27
San Mehatd9a4e352010-03-12 13:32:47 -080028#include <linux/kdev_t.h>
29
San Mehatb78a32c2010-01-10 13:02:12 -080030#define LOG_TAG "Vold"
31
32#include <cutils/log.h>
33
San Mehatd9a4e352010-03-12 13:32:47 -080034#include <sysutils/SocketClient.h>
35
San Mehatb78a32c2010-01-10 13:02:12 -080036#include "Devmapper.h"
37
Peter Bohm092aa1c2011-04-01 12:35:25 +020038#define DEVMAPPER_BUFFER_SIZE 4096
39
San Mehatd9a4e352010-03-12 13:32:47 -080040int Devmapper::dumpState(SocketClient *c) {
41
42 char *buffer = (char *) malloc(1024 * 64);
43 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -070044 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080045 return -1;
46 }
47 memset(buffer, 0, (1024 * 64));
48
Peter Bohm092aa1c2011-04-01 12:35:25 +020049 char *buffer2 = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
San Mehatd9a4e352010-03-12 13:32:47 -080050 if (!buffer2) {
San Mehat97ac40e2010-03-24 10:24:19 -070051 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080052 free(buffer);
53 return -1;
54 }
55
56 int fd;
57 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -070058 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080059 free(buffer);
60 free(buffer2);
61 return -1;
62 }
63
64 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
65 ioctlInit(io, (1024 * 64), NULL, 0);
66
67 if (ioctl(fd, DM_LIST_DEVICES, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -070068 SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080069 free(buffer);
70 free(buffer2);
71 close(fd);
72 return -1;
73 }
74
75 struct dm_name_list *n = (struct dm_name_list *) (((char *) buffer) + io->data_start);
76 if (!n->dev) {
77 free(buffer);
78 free(buffer2);
79 close(fd);
80 return 0;
81 }
82
83 unsigned nxt = 0;
84 do {
85 n = (struct dm_name_list *) (((char *) n) + nxt);
86
Peter Bohm092aa1c2011-04-01 12:35:25 +020087 memset(buffer2, 0, DEVMAPPER_BUFFER_SIZE);
San Mehatd9a4e352010-03-12 13:32:47 -080088 struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2;
Peter Bohm092aa1c2011-04-01 12:35:25 +020089 ioctlInit(io2, DEVMAPPER_BUFFER_SIZE, n->name, 0);
San Mehatd9a4e352010-03-12 13:32:47 -080090 if (ioctl(fd, DM_DEV_STATUS, io2)) {
91 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -070092 SLOGE("DM_DEV_STATUS ioctl failed (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080093 }
94 io2 = NULL;
95 }
96
97 char *tmp;
98 if (!io2) {
99 asprintf(&tmp, "%s %llu:%llu (no status available)", n->name, MAJOR(n->dev), MINOR(n->dev));
100 } else {
101 asprintf(&tmp, "%s %llu:%llu %d %d 0x%.8x %llu:%llu", n->name, MAJOR(n->dev),
102 MINOR(n->dev), io2->target_count, io2->open_count, io2->flags, MAJOR(io2->dev),
103 MINOR(io2->dev));
104 }
105 c->sendMsg(0, tmp, false);
106 free(tmp);
107 nxt = n->next;
108 } while (nxt);
109
110 free(buffer);
111 free(buffer2);
112 close(fd);
113 return 0;
114}
115
San Mehatb78a32c2010-01-10 13:02:12 -0800116void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize,
117 const char *name, unsigned flags) {
118 memset(io, 0, dataSize);
119 io->data_size = dataSize;
120 io->data_start = sizeof(struct dm_ioctl);
121 io->version[0] = 4;
122 io->version[1] = 0;
123 io->version[2] = 0;
124 io->flags = flags;
San Mehatd9a4e352010-03-12 13:32:47 -0800125 if (name) {
Peter Bohm092aa1c2011-04-01 12:35:25 +0200126 int ret = strlcpy(io->name, name, sizeof(io->name));
127 if (ret >= sizeof(io->name))
128 abort();
San Mehatd9a4e352010-03-12 13:32:47 -0800129 }
San Mehatb78a32c2010-01-10 13:02:12 -0800130}
131
132int Devmapper::lookupActive(const char *name, char *ubuffer, size_t len) {
Peter Bohm092aa1c2011-04-01 12:35:25 +0200133 char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
San Mehatb78a32c2010-01-10 13:02:12 -0800134 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700135 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800136 return -1;
137 }
138
139 int fd;
140 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700141 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800142 free(buffer);
143 return -1;
144 }
145
146 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
147
Peter Bohm092aa1c2011-04-01 12:35:25 +0200148 ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
San Mehatb78a32c2010-01-10 13:02:12 -0800149 if (ioctl(fd, DM_DEV_STATUS, io)) {
San Mehat8b8f71b2010-01-11 09:17:25 -0800150 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700151 SLOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800152 }
153 free(buffer);
154 close(fd);
155 return -1;
156 }
157 close(fd);
158
159 unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
160 free(buffer);
San Mehatb78a32c2010-01-10 13:02:12 -0800161 snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
162 return 0;
163}
164
San Mehat8b8f71b2010-01-11 09:17:25 -0800165int Devmapper::create(const char *name, const char *loopFile, const char *key,
166 unsigned int numSectors, char *ubuffer, size_t len) {
Peter Bohm092aa1c2011-04-01 12:35:25 +0200167 char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
San Mehatb78a32c2010-01-10 13:02:12 -0800168 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700169 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800170 return -1;
171 }
172
173 int fd;
174 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700175 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800176 free(buffer);
177 return -1;
178 }
179
180 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
181
182 // Create the DM device
Peter Bohm092aa1c2011-04-01 12:35:25 +0200183 ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
San Mehatb78a32c2010-01-10 13:02:12 -0800184
185 if (ioctl(fd, DM_DEV_CREATE, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700186 SLOGE("Error creating device mapping (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800187 free(buffer);
188 close(fd);
189 return -1;
190 }
191
192 // Set the legacy geometry
Peter Bohm092aa1c2011-04-01 12:35:25 +0200193 ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
San Mehatb78a32c2010-01-10 13:02:12 -0800194
195 char *geoParams = buffer + sizeof(struct dm_ioctl);
196 // 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
197 strcpy(geoParams, "0 64 63 0");
198 geoParams += strlen(geoParams) + 1;
199 geoParams = (char *) _align(geoParams, 8);
200 if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700201 SLOGE("Error setting device geometry (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800202 free(buffer);
203 close(fd);
204 return -1;
205 }
206
207 // Retrieve the device number we were allocated
Peter Bohm092aa1c2011-04-01 12:35:25 +0200208 ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
San Mehatb78a32c2010-01-10 13:02:12 -0800209 if (ioctl(fd, DM_DEV_STATUS, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700210 SLOGE("Error retrieving devmapper status (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800211 free(buffer);
212 close(fd);
213 return -1;
214 }
215
216 unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
San Mehatb78a32c2010-01-10 13:02:12 -0800217 snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
218
219 // Load the table
220 struct dm_target_spec *tgt;
221 tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
222
Peter Bohm092aa1c2011-04-01 12:35:25 +0200223 ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, DM_STATUS_TABLE_FLAG);
San Mehatb78a32c2010-01-10 13:02:12 -0800224 io->target_count = 1;
225 tgt->status = 0;
San Mehatfcf24fe2010-03-03 12:37:32 -0800226
San Mehatb78a32c2010-01-10 13:02:12 -0800227 tgt->sector_start = 0;
San Mehat8b8f71b2010-01-11 09:17:25 -0800228 tgt->length = numSectors;
San Mehatfcf24fe2010-03-03 12:37:32 -0800229
Peter Bohm092aa1c2011-04-01 12:35:25 +0200230 strlcpy(tgt->target_type, "crypt", sizeof(tgt->target_type));
San Mehatb78a32c2010-01-10 13:02:12 -0800231
232 char *cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
Peter Bohm092aa1c2011-04-01 12:35:25 +0200233 snprintf(cryptParams,
234 DEVMAPPER_BUFFER_SIZE - (sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec)),
235 "twofish %s 0 %s 0", key, loopFile);
San Mehatb78a32c2010-01-10 13:02:12 -0800236 cryptParams += strlen(cryptParams) + 1;
237 cryptParams = (char *) _align(cryptParams, 8);
238 tgt->next = cryptParams - buffer;
239
240 if (ioctl(fd, DM_TABLE_LOAD, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700241 SLOGE("Error loading mapping table (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800242 free(buffer);
243 close(fd);
244 return -1;
245 }
246
247 // Resume the new table
Peter Bohm092aa1c2011-04-01 12:35:25 +0200248 ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
San Mehatb78a32c2010-01-10 13:02:12 -0800249
250 if (ioctl(fd, DM_DEV_SUSPEND, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700251 SLOGE("Error Resuming (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800252 free(buffer);
253 close(fd);
254 return -1;
255 }
256
257 free(buffer);
258
San Mehat8c940ef2010-02-13 14:19:53 -0800259 close(fd);
San Mehatb78a32c2010-01-10 13:02:12 -0800260 return 0;
261}
262
263int Devmapper::destroy(const char *name) {
Peter Bohm092aa1c2011-04-01 12:35:25 +0200264 char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
San Mehatb78a32c2010-01-10 13:02:12 -0800265 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700266 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800267 return -1;
268 }
269
270 int fd;
271 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700272 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800273 free(buffer);
274 return -1;
275 }
276
277 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
278
279 // Create the DM device
Peter Bohm092aa1c2011-04-01 12:35:25 +0200280 ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
San Mehatb78a32c2010-01-10 13:02:12 -0800281
282 if (ioctl(fd, DM_DEV_REMOVE, io)) {
San Mehat0586d542010-01-12 15:38:59 -0800283 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700284 SLOGE("Error destroying device mapping (%s)", strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800285 }
San Mehatb78a32c2010-01-10 13:02:12 -0800286 free(buffer);
287 close(fd);
288 return -1;
289 }
290
291 free(buffer);
292 close(fd);
293 return 0;
294}
295
296void *Devmapper::_align(void *ptr, unsigned int a)
297{
298 register unsigned long agn = --a;
299
300 return (void *) (((unsigned long) ptr + agn) & ~agn);
301}
302