|
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 |
|