Clemens Fruhwirth wrote: > Also I should start to rewrite the backends to get rid of the options > struct. However, in the mean time could you just remove the use of > crypt_option except before that actual backend call? Then, the patch > is ready to merge (at least from my perspective) I replaced size with static variables for now (name, size) - ugly, but works:) See attachment. If you plan rewrite backend, maybe the whole identification of dm device could be changed to UUID - also cryptsetup should set this UUID for kernel device (+some prefix - LVM uses LVM, there can be probably LUKS... LUKS has alredy uuid in header, so it is just adding parameter to dm-ioctl call.) (This is nice for udev later for example.) Milan -- mbroz@xxxxxxxxxx
Use remapping to error target instead of calling udevsettle. --- lib/internal.h | 2 lib/libdevmapper.c | 143 ++++++++++++++++++++++++++++++++------------------- lib/setup.c | 2 luks/keyencryption.c | 25 ++++---- 4 files changed, 106 insertions(+), 66 deletions(-) Index: cryptsetup.my/lib/libdevmapper.c =================================================================== --- cryptsetup.my.orig/lib/libdevmapper.c 2008-09-09 23:22:16.000000000 +0200 +++ cryptsetup.my/lib/libdevmapper.c 2008-09-09 23:23:31.000000000 +0200 @@ -17,20 +17,7 @@ #define DEVICE_DIR "/dev" #define CRYPT_TARGET "crypt" - -#define UDEVSETTLE "/sbin/udevsettle" -#define UDEVADM "/sbin/udevadm" -#define UDEVADM_ARGS "settle --timeout=30" - -static void run_udevsettle(void) -{ -#ifndef SKIP_UDEVSETTLE - if (!access(UDEVADM, X_OK)) - system(UDEVADM " " UDEVADM_ARGS); - else if (!access(UDEVSETTLE, X_OK)) - system(UDEVSETTLE); -#endif -} +#define RETRY_COUNT 5 static void set_dm_error(int level, const char *file, int line, const char *f, ...) @@ -57,16 +44,6 @@ static void dm_exit(void) dm_lib_release(); } -static void flush_dm_workqueue(void) -{ - /* - * Unfortunately this is the only way to trigger libdevmapper's - * update_nodes function - */ - dm_exit(); - dm_init(); -} - static char *__lookup_dev(char *path, dev_t dev) { struct dirent *entry; @@ -159,6 +136,89 @@ out: return params; } +/* DM helpers */ +static int _dm_simple(int task, const char *name) +{ + int r = 0; + struct dm_task *dmt; + + if (!(dmt = dm_task_create(task))) + return 0; + + if (!dm_task_set_name(dmt, name)) + goto out; + + r = dm_task_run(dmt); + + out: + dm_task_destroy(dmt); + return r; +} + +static int _error_device(struct crypt_options *options) +{ + struct dm_task *dmt; + int r = 0; + + if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) + return 0; + + if (!dm_task_set_name(dmt, options->name)) + goto error; + + if (!dm_task_add_target(dmt, UINT64_C(0), options->size, "error", "")) + goto error; + + if (!dm_task_set_ro(dmt)) + goto error; + + if (!dm_task_no_open_count(dmt)) + goto error; + + if (!dm_task_run(dmt)) + goto error; + + if (!_dm_simple(DM_DEVICE_RESUME, options->name)) { + _dm_simple(DM_DEVICE_CLEAR, options->name); + goto error; + } + + r = 1; + +error: + dm_task_destroy(dmt); + return r; +} + +static int _dm_remove(struct crypt_options *options, int force) +{ + int r = -EINVAL; + int retries = force ? RETRY_COUNT : 1; + + /* If force flag is set, replace device with error, read-only target. + * it should stop processes from reading it and also removed underlying + * device from mapping, so it is usable again. + * Force flag should be used only for temporary devices, which are + * intended to work inside cryptsetup only! + * Anyway, if some process try to read temporary cryptsetup device, + * it is bug - no other process should try touch it (e.g. udev). + */ + if (force) { + _error_device(options); + retries = RETRY_COUNT; + } + + do { + r = _dm_simple(DM_DEVICE_REMOVE, options->name) ? 0 : -EINVAL; + if (--retries) + sleep(1); + } while (r == -EINVAL && retries); + + dm_task_update_nodes(); + + return r; +} + static int dm_create_device(int reload, struct crypt_options *options, const char *key) { @@ -198,24 +258,14 @@ static int dm_create_device(int reload, if (dmi.read_only) options->flags |= CRYPT_FLAG_READONLY; - /* run udevsettle to avoid a race in libdevmapper causing busy dm devices */ - run_udevsettle(); - r = 0; - out: if (r < 0 && !reload) { char *error = (char *)get_error(); if (error) error = strdup(error); - if (dmt) - dm_task_destroy(dmt); - if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) - goto out_restore_error; - if (!dm_task_set_name(dmt, options->name)) - goto out_restore_error; - if (!dm_task_run(dmt)) + if (!_dm_remove(options, 0)) goto out_restore_error; out_restore_error: @@ -231,7 +281,7 @@ out_no_removal: dm_task_destroy(dmt); if(dmt_query) dm_task_destroy(dmt_query); - flush_dm_workqueue(); + dm_task_update_nodes(); return r; } @@ -359,25 +409,12 @@ out: return r; } -static int dm_remove_device(struct crypt_options *options) +static int dm_remove_device(int force, struct crypt_options *options) { - struct dm_task *dmt; - int r = -EINVAL; + if (!options || !options->name) + return -EINVAL; - if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) - goto out; - if (!dm_task_set_name(dmt, options->name)) - goto out; - if (!dm_task_run(dmt)) - goto out; - - r = 0; - -out: - if (dmt) - dm_task_destroy(dmt); - flush_dm_workqueue(); - return r; + return _dm_remove(options, force);; } Index: cryptsetup.my/lib/internal.h =================================================================== --- cryptsetup.my.orig/lib/internal.h 2008-09-09 23:22:16.000000000 +0200 +++ cryptsetup.my/lib/internal.h 2008-09-09 23:23:31.000000000 +0200 @@ -40,7 +40,7 @@ struct setup_backend { const char *key); int (*status)(int details, struct crypt_options *options, char **key); - int (*remove)(struct crypt_options *options); + int (*remove)(int force, struct crypt_options *options); const char * (*dir)(void); }; Index: cryptsetup.my/lib/setup.c =================================================================== --- cryptsetup.my.orig/lib/setup.c 2008-09-09 23:22:16.000000000 +0200 +++ cryptsetup.my/lib/setup.c 2008-09-09 23:23:31.000000000 +0200 @@ -369,7 +369,7 @@ static int __crypt_remove_device(int arg return -EBUSY; } - return backend->remove(options); + return backend->remove(0, options); } static int __crypt_luks_format(int arg, struct setup_backend *backend, struct crypt_options *options) Index: cryptsetup.my/luks/keyencryption.c =================================================================== --- cryptsetup.my.orig/luks/keyencryption.c 2008-09-09 23:22:16.000000000 +0200 +++ cryptsetup.my/luks/keyencryption.c 2008-09-09 23:32:35.000000000 +0200 @@ -45,6 +45,11 @@ static inline int round_up_modulo(int x, return div_round_up(x, m) * m; } +static struct setup_backend *cleaner_backend=NULL; +static const char *cleaner_name=NULL; +static uint64_t cleaner_size = 0; +static int devfd=-1; + static int setup_mapping(const char *cipher, const char *name, const char *device, unsigned int payloadOffset, const char *key, size_t keyLength, @@ -52,7 +57,7 @@ static int setup_mapping(const char *cip struct setup_backend *backend, int mode) { - struct crypt_options k; + struct crypt_options k = {0}; struct crypt_options *options = &k; int device_sector_size = sector_size_for_device(device); int r; @@ -66,6 +71,7 @@ static int setup_mapping(const char *cip return -EINVAL; } options->size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE; + cleaner_size = options->size; options->offset = sector; options->cipher = cipher; @@ -87,25 +93,21 @@ static int setup_mapping(const char *cip return r; } -static int clear_mapping(const char *name, struct setup_backend *backend) +static int clear_mapping(const char *name, uint64_t size, struct setup_backend *backend) { - struct crypt_options options; + struct crypt_options options = {0}; options.name=name; - return backend->remove(&options); + options.size = size; + return backend->remove(1, &options); } -/* I miss closures in C! */ -static struct setup_backend *cleaner_backend=NULL; -static const char *cleaner_name=NULL; -static int devfd=-1; - static void sigint_handler(int sig) { if(devfd >= 0) close(devfd); devfd = -1; if(cleaner_backend && cleaner_name) - clear_mapping(cleaner_name, cleaner_backend); + clear_mapping(cleaner_name, cleaner_size, cleaner_backend); signal(SIGINT, SIG_DFL); kill(getpid(), SIGINT); } @@ -163,11 +165,12 @@ static int LUKS_endec_template(char *src close(devfd); devfd = -1; out2: - clear_mapping(name,backend); + clear_mapping(cleaner_name, cleaner_size, cleaner_backend); out1: signal(SIGINT, SIG_DFL); cleaner_name = NULL; cleaner_backend = NULL; + cleaner_size = 0; free(dmCipherSpec); free(fullpath); free(name);
--------------------------------------------------------------------- dm-crypt mailing list - http://www.saout.de/misc/dm-crypt/ To unsubscribe, e-mail: dm-crypt-unsubscribe@xxxxxxxx For additional commands, e-mail: dm-crypt-help@xxxxxxxx