17
17
#define DEVICE_DIR "/dev"
19
19
#define CRYPT_TARGET "crypt"
21
#define UDEVSETTLE "/sbin/udevsettle"
23
static void run_udevsettle(void)
28
22
static void set_dm_error(int level, const char *file, int line,
29
23
const char *f, ...)
35
static int _dm_simple(int task, const char *name);
41
37
static int dm_init(void)
43
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?");
44
45
return 1; /* unsafe memory */
147
static int _dm_simple(int task, const char *name)
152
if (!(dmt = dm_task_create(task)))
155
if (!dm_task_set_name(dmt, name))
158
r = dm_task_run(dmt);
161
dm_task_destroy(dmt);
165
static int _error_device(struct crypt_options *options)
170
if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
173
if (!dm_task_set_name(dmt, options->name))
176
if (!dm_task_add_target(dmt, UINT64_C(0), options->size, "error", ""))
179
if (!dm_task_set_ro(dmt))
182
if (!dm_task_no_open_count(dmt))
185
if (!dm_task_run(dmt))
188
if (!_dm_simple(DM_DEVICE_RESUME, options->name)) {
189
_dm_simple(DM_DEVICE_CLEAR, options->name);
196
dm_task_destroy(dmt);
200
static int _dm_remove(struct crypt_options *options, int force)
203
int retries = force ? RETRY_COUNT : 1;
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).
214
_error_device(options);
215
retries = RETRY_COUNT;
219
r = _dm_simple(DM_DEVICE_REMOVE, options->name) ? 0 : -EINVAL;
222
} while (r == -EINVAL && retries);
224
dm_task_update_nodes();
155
229
static int dm_create_device(int reload, struct crypt_options *options,
191
265
if (dmi.read_only)
192
266
options->flags |= CRYPT_FLAG_READONLY;
194
/* run udevsettle to avoid a race in libdevmapper causing busy dm devices */
200
270
if (r < 0 && !reload) {
201
271
char *error = (char *)get_error();
203
273
error = strdup(error);
205
dm_task_destroy(dmt);
207
if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
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))
275
if (!_dm_remove(options, 0))
212
276
goto out_restore_error;
214
278
out_restore_error:
355
static int dm_remove_device(struct crypt_options *options)
419
static int dm_remove_device(int force, struct crypt_options *options)
360
if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
362
if (!dm_task_set_name(dmt, options->name))
364
if (!dm_task_run(dmt))
371
dm_task_destroy(dmt);
372
flush_dm_workqueue();
421
if (!options || !options->name)
424
return _dm_remove(options, force);;