Lines 17-29
Link Here
|
17 |
#define DEVICE_DIR "/dev" |
17 |
#define DEVICE_DIR "/dev" |
18 |
|
18 |
|
19 |
#define CRYPT_TARGET "crypt" |
19 |
#define CRYPT_TARGET "crypt" |
20 |
|
20 |
#define RETRY_COUNT 5 |
21 |
#define UDEVSETTLE "/sbin/udevsettle" |
|
|
22 |
|
23 |
static void run_udevsettle(void) |
24 |
{ |
25 |
system(UDEVSETTLE); |
26 |
} |
27 |
|
21 |
|
28 |
static void set_dm_error(int level, const char *file, int line, |
22 |
static void set_dm_error(int level, const char *file, int line, |
29 |
const char *f, ...) |
23 |
const char *f, ...) |
Lines 38-46
static void set_dm_error(int level, cons
Link Here
|
38 |
va_end(va); |
32 |
va_end(va); |
39 |
} |
33 |
} |
40 |
|
34 |
|
|
|
35 |
static int _dm_simple(int task, const char *name); |
36 |
|
41 |
static int dm_init(void) |
37 |
static int dm_init(void) |
42 |
{ |
38 |
{ |
43 |
dm_log_init(set_dm_error); |
39 |
dm_log_init(set_dm_error); |
|
|
40 |
if (!_dm_simple(DM_DEVICE_LIST_VERSIONS, "test")) { |
41 |
set_error("Cannot communicate with device-mapper. Is the dm_mod module loaded?"); |
42 |
return -1; |
43 |
} |
44 |
|
44 |
return 1; /* unsafe memory */ |
45 |
return 1; /* unsafe memory */ |
45 |
} |
46 |
} |
46 |
|
47 |
|
Lines 50-65
static void dm_exit(void)
Link Here
|
50 |
dm_lib_release(); |
51 |
dm_lib_release(); |
51 |
} |
52 |
} |
52 |
|
53 |
|
53 |
static void flush_dm_workqueue(void) |
|
|
54 |
{ |
55 |
/* |
56 |
* Unfortunately this is the only way to trigger libdevmapper's |
57 |
* update_nodes function |
58 |
*/ |
59 |
dm_exit(); |
60 |
dm_init(); |
61 |
} |
62 |
|
63 |
static char *__lookup_dev(char *path, dev_t dev) |
54 |
static char *__lookup_dev(char *path, dev_t dev) |
64 |
{ |
55 |
{ |
65 |
struct dirent *entry; |
56 |
struct dirent *entry; |
Lines 152-157
out:
Link Here
|
152 |
return params; |
143 |
return params; |
153 |
} |
144 |
} |
154 |
|
145 |
|
|
|
146 |
/* DM helpers */ |
147 |
static int _dm_simple(int task, const char *name) |
148 |
{ |
149 |
int r = 0; |
150 |
struct dm_task *dmt; |
151 |
|
152 |
if (!(dmt = dm_task_create(task))) |
153 |
return 0; |
154 |
|
155 |
if (!dm_task_set_name(dmt, name)) |
156 |
goto out; |
157 |
|
158 |
r = dm_task_run(dmt); |
159 |
|
160 |
out: |
161 |
dm_task_destroy(dmt); |
162 |
return r; |
163 |
} |
164 |
|
165 |
static int _error_device(struct crypt_options *options) |
166 |
{ |
167 |
struct dm_task *dmt; |
168 |
int r = 0; |
169 |
|
170 |
if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) |
171 |
return 0; |
172 |
|
173 |
if (!dm_task_set_name(dmt, options->name)) |
174 |
goto error; |
175 |
|
176 |
if (!dm_task_add_target(dmt, UINT64_C(0), options->size, "error", "")) |
177 |
goto error; |
178 |
|
179 |
if (!dm_task_set_ro(dmt)) |
180 |
goto error; |
181 |
|
182 |
if (!dm_task_no_open_count(dmt)) |
183 |
goto error; |
184 |
|
185 |
if (!dm_task_run(dmt)) |
186 |
goto error; |
187 |
|
188 |
if (!_dm_simple(DM_DEVICE_RESUME, options->name)) { |
189 |
_dm_simple(DM_DEVICE_CLEAR, options->name); |
190 |
goto error; |
191 |
} |
192 |
|
193 |
r = 1; |
194 |
|
195 |
error: |
196 |
dm_task_destroy(dmt); |
197 |
return r; |
198 |
} |
199 |
|
200 |
static int _dm_remove(struct crypt_options *options, int force) |
201 |
{ |
202 |
int r = -EINVAL; |
203 |
int retries = force ? RETRY_COUNT : 1; |
204 |
|
205 |
/* If force flag is set, replace device with error, read-only target. |
206 |
* it should stop processes from reading it and also removed underlying |
207 |
* device from mapping, so it is usable again. |
208 |
* Force flag should be used only for temporary devices, which are |
209 |
* intended to work inside cryptsetup only! |
210 |
* Anyway, if some process try to read temporary cryptsetup device, |
211 |
* it is bug - no other process should try touch it (e.g. udev). |
212 |
*/ |
213 |
if (force) { |
214 |
_error_device(options); |
215 |
retries = RETRY_COUNT; |
216 |
} |
217 |
|
218 |
do { |
219 |
r = _dm_simple(DM_DEVICE_REMOVE, options->name) ? 0 : -EINVAL; |
220 |
if (--retries) |
221 |
sleep(1); |
222 |
} while (r == -EINVAL && retries); |
223 |
|
224 |
dm_task_update_nodes(); |
225 |
|
226 |
return r; |
227 |
} |
228 |
|
155 |
static int dm_create_device(int reload, struct crypt_options *options, |
229 |
static int dm_create_device(int reload, struct crypt_options *options, |
156 |
const char *key) |
230 |
const char *key) |
157 |
{ |
231 |
{ |
Lines 191-214
static int dm_create_device(int reload,
Link Here
|
191 |
if (dmi.read_only) |
265 |
if (dmi.read_only) |
192 |
options->flags |= CRYPT_FLAG_READONLY; |
266 |
options->flags |= CRYPT_FLAG_READONLY; |
193 |
|
267 |
|
194 |
/* run udevsettle to avoid a race in libdevmapper causing busy dm devices */ |
|
|
195 |
run_udevsettle(); |
196 |
|
197 |
r = 0; |
268 |
r = 0; |
198 |
|
|
|
199 |
out: |
269 |
out: |
200 |
if (r < 0 && !reload) { |
270 |
if (r < 0 && !reload) { |
201 |
char *error = (char *)get_error(); |
271 |
char *error = (char *)get_error(); |
202 |
if (error) |
272 |
if (error) |
203 |
error = strdup(error); |
273 |
error = strdup(error); |
204 |
if (dmt) |
|
|
205 |
dm_task_destroy(dmt); |
206 |
|
274 |
|
207 |
if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) |
275 |
if (!_dm_remove(options, 0)) |
208 |
goto out_restore_error; |
|
|
209 |
if (!dm_task_set_name(dmt, options->name)) |
210 |
goto out_restore_error; |
211 |
if (!dm_task_run(dmt)) |
212 |
goto out_restore_error; |
276 |
goto out_restore_error; |
213 |
|
277 |
|
214 |
out_restore_error: |
278 |
out_restore_error: |
Lines 224-230
out_no_removal:
Link Here
|
224 |
dm_task_destroy(dmt); |
288 |
dm_task_destroy(dmt); |
225 |
if(dmt_query) |
289 |
if(dmt_query) |
226 |
dm_task_destroy(dmt_query); |
290 |
dm_task_destroy(dmt_query); |
227 |
flush_dm_workqueue(); |
291 |
dm_task_update_nodes(); |
228 |
return r; |
292 |
return r; |
229 |
} |
293 |
} |
230 |
|
294 |
|
Lines 352-376
out:
Link Here
|
352 |
return r; |
416 |
return r; |
353 |
} |
417 |
} |
354 |
|
418 |
|
355 |
static int dm_remove_device(struct crypt_options *options) |
419 |
static int dm_remove_device(int force, struct crypt_options *options) |
356 |
{ |
420 |
{ |
357 |
struct dm_task *dmt; |
421 |
if (!options || !options->name) |
358 |
int r = -EINVAL; |
422 |
return -EINVAL; |
359 |
|
|
|
360 |
if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) |
361 |
goto out; |
362 |
if (!dm_task_set_name(dmt, options->name)) |
363 |
goto out; |
364 |
if (!dm_task_run(dmt)) |
365 |
goto out; |
366 |
|
367 |
r = 0; |
368 |
|
423 |
|
369 |
out: |
424 |
return _dm_remove(options, force);; |
370 |
if (dmt) |
|
|
371 |
dm_task_destroy(dmt); |
372 |
flush_dm_workqueue(); |
373 |
return r; |
374 |
} |
425 |
} |
375 |
|
426 |
|
376 |
|
427 |
|