blob: c9482bf3473b2feb674876e579f0fda35932c18c [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>
22
23#include <sys/types.h>
24#include <sys/ioctl.h>
25#include <sys/stat.h>
26
San Mehatd9a4e352010-03-12 13:32:47 -080027#include <linux/kdev_t.h>
28
San Mehatb78a32c2010-01-10 13:02:12 -080029#define LOG_TAG "Vold"
30
31#include <cutils/log.h>
32
San Mehatd9a4e352010-03-12 13:32:47 -080033#include <sysutils/SocketClient.h>
34
San Mehatb78a32c2010-01-10 13:02:12 -080035#include "Devmapper.h"
36
San Mehatd9a4e352010-03-12 13:32:47 -080037int Devmapper::dumpState(SocketClient *c) {
38
39 char *buffer = (char *) malloc(1024 * 64);
40 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -070041 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080042 return -1;
43 }
44 memset(buffer, 0, (1024 * 64));
45
46 char *buffer2 = (char *) malloc(4096);
47 if (!buffer2) {
San Mehat97ac40e2010-03-24 10:24:19 -070048 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080049 free(buffer);
50 return -1;
51 }
52
53 int fd;
54 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -070055 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080056 free(buffer);
57 free(buffer2);
58 return -1;
59 }
60
61 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
62 ioctlInit(io, (1024 * 64), NULL, 0);
63
64 if (ioctl(fd, DM_LIST_DEVICES, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -070065 SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080066 free(buffer);
67 free(buffer2);
68 close(fd);
69 return -1;
70 }
71
72 struct dm_name_list *n = (struct dm_name_list *) (((char *) buffer) + io->data_start);
73 if (!n->dev) {
74 free(buffer);
75 free(buffer2);
76 close(fd);
77 return 0;
78 }
79
80 unsigned nxt = 0;
81 do {
82 n = (struct dm_name_list *) (((char *) n) + nxt);
83
84 memset(buffer2, 0, 4096);
85 struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2;
86 ioctlInit(io2, 4096, n->name, 0);
87 if (ioctl(fd, DM_DEV_STATUS, io2)) {
88 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -070089 SLOGE("DM_DEV_STATUS ioctl failed (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080090 }
91 io2 = NULL;
92 }
93
94 char *tmp;
95 if (!io2) {
96 asprintf(&tmp, "%s %llu:%llu (no status available)", n->name, MAJOR(n->dev), MINOR(n->dev));
97 } else {
98 asprintf(&tmp, "%s %llu:%llu %d %d 0x%.8x %llu:%llu", n->name, MAJOR(n->dev),
99 MINOR(n->dev), io2->target_count, io2->open_count, io2->flags, MAJOR(io2->dev),
100 MINOR(io2->dev));
101 }
102 c->sendMsg(0, tmp, false);
103 free(tmp);
104 nxt = n->next;
105 } while (nxt);
106
107 free(buffer);
108 free(buffer2);
109 close(fd);
110 return 0;
111}
112
San Mehatb78a32c2010-01-10 13:02:12 -0800113void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize,
114 const char *name, unsigned flags) {
115 memset(io, 0, dataSize);
116 io->data_size = dataSize;
117 io->data_start = sizeof(struct dm_ioctl);
118 io->version[0] = 4;
119 io->version[1] = 0;
120 io->version[2] = 0;
121 io->flags = flags;
San Mehatd9a4e352010-03-12 13:32:47 -0800122 if (name) {
123 strncpy(io->name, name, sizeof(io->name));
124 }
San Mehatb78a32c2010-01-10 13:02:12 -0800125}
126
127int Devmapper::lookupActive(const char *name, char *ubuffer, size_t len) {
128 char *buffer = (char *) malloc(4096);
129 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700130 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800131 return -1;
132 }
133
134 int fd;
135 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700136 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800137 free(buffer);
138 return -1;
139 }
140
141 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
142
143 ioctlInit(io, 4096, name, 0);
144 if (ioctl(fd, DM_DEV_STATUS, io)) {
San Mehat8b8f71b2010-01-11 09:17:25 -0800145 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700146 SLOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800147 }
148 free(buffer);
149 close(fd);
150 return -1;
151 }
152 close(fd);
153
154 unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
155 free(buffer);
San Mehatb78a32c2010-01-10 13:02:12 -0800156 snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
157 return 0;
158}
159
San Mehat8b8f71b2010-01-11 09:17:25 -0800160int Devmapper::create(const char *name, const char *loopFile, const char *key,
161 unsigned int numSectors, char *ubuffer, size_t len) {
San Mehatb78a32c2010-01-10 13:02:12 -0800162 char *buffer = (char *) malloc(4096);
163 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700164 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800165 return -1;
166 }
167
168 int fd;
169 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700170 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800171 free(buffer);
172 return -1;
173 }
174
175 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
176
177 // Create the DM device
178 ioctlInit(io, 4096, name, 0);
179
180 if (ioctl(fd, DM_DEV_CREATE, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700181 SLOGE("Error creating device mapping (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800182 free(buffer);
183 close(fd);
184 return -1;
185 }
186
187 // Set the legacy geometry
188 ioctlInit(io, 4096, name, 0);
189
190 char *geoParams = buffer + sizeof(struct dm_ioctl);
191 // 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
192 strcpy(geoParams, "0 64 63 0");
193 geoParams += strlen(geoParams) + 1;
194 geoParams = (char *) _align(geoParams, 8);
195 if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700196 SLOGE("Error setting device geometry (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800197 free(buffer);
198 close(fd);
199 return -1;
200 }
201
202 // Retrieve the device number we were allocated
203 ioctlInit(io, 4096, name, 0);
204 if (ioctl(fd, DM_DEV_STATUS, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700205 SLOGE("Error retrieving devmapper status (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800206 free(buffer);
207 close(fd);
208 return -1;
209 }
210
211 unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
San Mehatb78a32c2010-01-10 13:02:12 -0800212 snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
213
214 // Load the table
215 struct dm_target_spec *tgt;
216 tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
217
218 ioctlInit(io, 4096, name, DM_STATUS_TABLE_FLAG);
219 io->target_count = 1;
220 tgt->status = 0;
San Mehatfcf24fe2010-03-03 12:37:32 -0800221
San Mehatb78a32c2010-01-10 13:02:12 -0800222 tgt->sector_start = 0;
San Mehat8b8f71b2010-01-11 09:17:25 -0800223 tgt->length = numSectors;
San Mehatfcf24fe2010-03-03 12:37:32 -0800224
San Mehatb78a32c2010-01-10 13:02:12 -0800225 strcpy(tgt->target_type, "crypt");
226
227 char *cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
228 sprintf(cryptParams, "twofish %s 0 %s 0", key, loopFile);
229 cryptParams += strlen(cryptParams) + 1;
230 cryptParams = (char *) _align(cryptParams, 8);
231 tgt->next = cryptParams - buffer;
232
233 if (ioctl(fd, DM_TABLE_LOAD, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700234 SLOGE("Error loading mapping table (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800235 free(buffer);
236 close(fd);
237 return -1;
238 }
239
240 // Resume the new table
241 ioctlInit(io, 4096, name, 0);
242
243 if (ioctl(fd, DM_DEV_SUSPEND, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700244 SLOGE("Error Resuming (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800245 free(buffer);
246 close(fd);
247 return -1;
248 }
249
250 free(buffer);
251
San Mehat8c940ef2010-02-13 14:19:53 -0800252 close(fd);
San Mehatb78a32c2010-01-10 13:02:12 -0800253 return 0;
254}
255
256int Devmapper::destroy(const char *name) {
257 char *buffer = (char *) malloc(4096);
258 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700259 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800260 return -1;
261 }
262
263 int fd;
264 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700265 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800266 free(buffer);
267 return -1;
268 }
269
270 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
271
272 // Create the DM device
273 ioctlInit(io, 4096, name, 0);
274
275 if (ioctl(fd, DM_DEV_REMOVE, io)) {
San Mehat0586d542010-01-12 15:38:59 -0800276 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700277 SLOGE("Error destroying device mapping (%s)", strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800278 }
San Mehatb78a32c2010-01-10 13:02:12 -0800279 free(buffer);
280 close(fd);
281 return -1;
282 }
283
284 free(buffer);
285 close(fd);
286 return 0;
287}
288
289void *Devmapper::_align(void *ptr, unsigned int a)
290{
291 register unsigned long agn = --a;
292
293 return (void *) (((unsigned long) ptr + agn) & ~agn);
294}
295