From: garlicbread@ntlworld.com To: evms-devel@lists.sourceforge.net Date: 2005-10-09 10:22 am Hi, Some of you may find this interesting a patch against evms 2.5.3 to enable device-mapper devices for input into evms This is useful for things such as layering evms on top of dmraid and dm-crypt without the need for loop back devices (I've tried this with dmraid and I think this should also work for dm-crypt) I'm posting this from a web-mail system at the moment so I hope the patch gets through okay a better approach would probably be to have a seperate plugin to control the aspects of device-mapper raid / crypt within evms perhaps as some form of region layer but at the moment I'm trying to see if I can write a reiser4 plugin only device mapper targets stated in the new config section will be picked up (no wildcards) devices will show up with a prefix of dm/ it's best to specify the entire disk target and let evms determine the seperate partitions for itself it may even be possible to layer an evms volume on top of another evms volume (assuming your crazy enough to try) but I wouldn't advise it :) Apply with: cd /usr/src/evms-2.5.5/ patch -p0 < evms-2.5.5-userdm-0.1.patch make make install Index: doc/evms.conf =================================================================== RCS file: /cvsroot/evms/evms2/engine/doc/evms.conf,v retrieving revision 1.30 diff -u -r1.30 evms.conf --- doc/evms.conf 23 Feb 2006 15:49:43 -0000 1.30 +++ doc/evms.conf 6 Mar 2006 22:11:34 -0000 @@ -267,3 +267,22 @@ # can_create_sb_1 = yes } +# User devmapper section +# This allows us to use a device-mapper device directly as a disk +# without the need for loopback +# Be careful not to specify any targets that are created by evms +# This can be useful for any devices created via dmraid or other means + +# In order for this to work "dm*" has to be in the list of includes + +devmapper { + # This needs to be set to yes to enable + #dm_user = yes + + # List of targets to discover as disks + # These are the target names as seen with "dmsetup ls" + # only specific targets can be used + # we need to avoid evms created targets + #dm_user_targets = [ raid1_device raid0_device ] +} + Index: engine/dm-targets.c =================================================================== RCS file: /cvsroot/evms/evms2/engine/engine/dm-targets.c,v retrieving revision 1.13 diff -u -r1.13 dm-targets.c --- engine/dm-targets.c 7 Nov 2005 15:46:41 -0000 1.13 +++ engine/dm-targets.c 6 Mar 2006 22:11:34 -0000 @@ -800,28 +800,39 @@ * Fill in a mirror target structure based on an ASCII table string of the form: * []* [: ]{2,} * - * Currently, log_type will always be "core", num_log_params is 1, and + * Currently, log_type will always be "core", num_log_params is 1 or 2, and * log_params is chunk-size (in sectors). **/ static int mirror_translate_params(dm_target_t *target) { dm_target_mirror_t *mirror = target->data.mirror; char *params = target->params; - int i, rc; + int i, rc, num_opts; LOG_PROC_ENTRY(); - /* Skip "core 1" at the start of the string. */ - params = next_token(params); + /* Skip "core" at the start of the string. */ params = next_token(params); - rc = sscanf(params, "%u %u", &mirror->chunk_size, &mirror->num_mirrors); + /* get the number of options for core and the chunk size */ + rc = sscanf(params, "%u %u", &num_opts, &mirror->chunk_size); if (rc != 2) { rc = EINVAL; goto out; } - params = next_token(params); + + /* skip the options for core based on num_opts */ + for (i = 0; i < num_opts; i++) { + params = next_token(params); + } + + /* get the number of mirrors */ + rc = sscanf(params, "%u", &mirror->num_mirrors); + if (rc != 1) { + rc = EINVAL; + goto out; + } params = next_token(params); for (i = 0; i < mirror->num_mirrors; i++) { @@ -855,13 +866,33 @@ static int mirror_pretranslate_params(char *params, u_int32_t *num_devs, u_int32_t *num_groups) { - int rc; + int rc, i, num_opts = 0; + char *num_devs_point; LOG_PROC_ENTRY(); - rc = sscanf(params, "%*s %*d %*u %u", num_devs); + /* The mirror target can have more than 1 option + this affects the location of the number of member disks */ + + rc = sscanf(params, "%*s %u", &num_opts); + if (rc != 1) { + rc = EINVAL; + goto out; + } + + /* skip "core " */ + num_devs_point = next_token(params); + num_devs_point = next_token(params); + + /* skip the options for core based on num_opts */ + for (i = 0; i < num_opts; i++) { + num_devs_point = next_token(params); + } + + rc = sscanf(num_devs_point, "%u", num_devs); rc = (rc != 1) ? EINVAL : 0; +out: LOG_PROC_EXIT_INT(rc); return rc; } Index: plugins/disk/localdskmgr.c =================================================================== RCS file: /cvsroot/evms/evms2/engine/plugins/disk/localdskmgr.c,v retrieving revision 1.122 diff -u -r1.122 localdskmgr.c --- plugins/disk/localdskmgr.c 24 Feb 2006 19:53:21 -0000 1.122 +++ plugins/disk/localdskmgr.c 6 Mar 2006 22:11:34 -0000 @@ -1335,13 +1335,14 @@ rc = EngFncs->dm_get_targets(disk, &targets); if (rc) { LOG_ERROR("Error getting DM mapping for disk %s.\n", disk->name); + rc=0; goto out; } /* Reject all non-multipath devices. */ if (targets->type != DM_TARGET_MULTIPATH) { LOG_DEBUG("Disk %s is not a multipath device.\n", disk->name); - rc = EINVAL; + //rc = EINVAL; goto out; } @@ -1541,6 +1542,98 @@ } /** + * check_user_devicemapper + * + * Check if this disk is a User created DM device. + **/ +static int check_user_devicemapper(storage_object_t * disk) +{ + dm_device_list_t * dm_list, * dm_entry; + dm_target_t * targets = NULL; + local_disk_t * ld = disk->private_data; + int rc = 0, dm_user_targets_count = 0, i, dmup_len; + boolean user_dm_enable; + const char * const * dm_user_targets; + char * dm_user_prefix = "dm/"; + + LOG_ENTRY(); + + /* Get the list of active DM devices. */ + dm_list = get_dm_device_list(); + if (!dm_list) { + LOG_WARNING("Cannot get list of DM devices.\n"); + goto out; + } + + /* Search the DM list for an entry that matches this disk. */ + dm_entry = find_disk_in_dm_devices(disk, dm_list); + if (!dm_entry) { + LOG_DEBUG("Disk %s is not a DM device.\n", disk->name); + goto out; + } + + user_dm_enable = FALSE; + EngFncs->get_config_bool("devmapper.dm_user", &user_dm_enable); + + EngFncs->get_config_string_array("devmapper.dm_user_targets", + &dm_user_targets_count, &dm_user_targets); + + if (user_dm_enable == FALSE) { + LOG_DEBUG("devmapper.dm_user not enabled.\n"); + rc = EINVAL; + goto out; + } + + /* search the named targets in the config for the DM name*/ + user_dm_enable = FALSE; + for (i = 0; i < dm_user_targets_count; i++) { + if (strncmp(dm_user_targets[i], dm_entry->name, EVMS_NAME_SIZE) == 0) { + user_dm_enable = TRUE; + } + } + + if (user_dm_enable == FALSE) { + LOG_DEBUG("%s not found in devmapper.dm_user_targets.\n", dm_entry->name); + rc = EINVAL; + goto out; + } + + /* Get the DM mapping for this disk. */ + /* we can use this in the future if we need to, and it's good to check */ + strncpy(disk->name, dm_entry->name, EVMS_NAME_SIZE); + rc = EngFncs->dm_get_targets(disk, &targets); + if (rc) { + LOG_ERROR("Error getting DM mapping for disk %s.\n", disk->name); + goto out; + } + + /* Copy the DM name to this disk. */ + dmup_len = strlen(dm_user_prefix); + LOG_DEBUG("Changing disk name from %s to %s%s.\n", + disk->name, dm_user_prefix ,dm_entry->name); + + strncpy(disk->name, dm_user_prefix, dmup_len); + strncpy((disk->name)+dmup_len, dm_entry->name, EVMS_NAME_SIZE-dmup_len); + + /* Reject all multipath devices that + * were created by other EVMS plugins. + */ + rc = check_multipath_name(disk); + if (rc) { + LOG_DEBUG("Multipath disk %s belongs to another EVMS plugin.\n", + disk->name); + goto out; + } + + ld->flags |= LD_FLAG_USERDM; + +out: + /*EngFncs->dm_deallocate_targets(targets); */ + LOG_EXIT_INT(rc); + return rc; +} + +/** * get_geometry * * First try to get the geometry from the partition table (if it exists). @@ -1834,6 +1927,13 @@ /* Get the disk's hard-sector-size. */ get_hardsector_size(&working_disk); + /* Check for User created DM devices. */ + rc = check_user_devicemapper(&working_disk); + if (rc) { + close_dev(&working_disk); + continue; + } + /* Get the disk's geometry. */ get_geometry(&working_disk); Index: plugins/disk/localdskmgr.h =================================================================== RCS file: /cvsroot/evms/evms2/engine/plugins/disk/localdskmgr.h,v retrieving revision 1.27 diff -u -r1.27 localdskmgr.h --- plugins/disk/localdskmgr.h 24 Feb 2006 17:00:44 -0000 1.27 +++ plugins/disk/localdskmgr.h 6 Mar 2006 22:11:34 -0000 @@ -93,6 +93,7 @@ #define LD_FLAG_MULTIPATH (1 << 0) #define LD_FLAG_IDE (1 << 1) #define LD_FLAG_SCSI (1 << 2) +#define LD_FLAG_USERDM (1 << 3) extern engine_functions_t *EngFncs; extern plugin_record_t *my_plugin_record;