From f134a703d59cab7791ead3eb7f5e77038dbae4dc Mon Sep 17 00:00:00 2001 From: Tomohiro Kusumi Date: Mon, 19 Oct 2015 21:36:16 +0900 Subject: [PATCH 1/1] sys/dev/disk/dm: Don't implement "status" as a subset of "table" [1/2] DragonFly's (and NetBSD's) dm implements "status" and "table" of dmsetup(8) using the same handler dm_table_status_ioctl(), and sees "status" as a subset of "table", however this is wrong. Linux dm implements these two as different subcommands, so the way these two are implemented in BSDs breaks compatibility with Linux dm. Actually it has never broke compatibility with Linux dm until dm-delay target was added, because targets that were available till then happened to have a blank "status" implementation, which ended up being a subset of "table". This is not the case with dm-delay target in Linux with different implmentation for each, and this commit is to maintain the compatibility with Linux. --- sys/dev/disk/dm/dm.h | 3 ++- sys/dev/disk/dm/dm_ioctl.c | 18 +++++++++++------- .../disk/dm/targets/delay/dm_target_delay.c | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/sys/dev/disk/dm/dm.h b/sys/dev/disk/dm/dm.h index 9fdaa7a936..6ba418fd39 100644 --- a/sys/dev/disk/dm/dm.h +++ b/sys/dev/disk/dm/dm.h @@ -180,10 +180,11 @@ typedef struct dm_target { int (*deps) (dm_table_entry_t *, prop_array_t); /* - * Status routine is called to get params string, which is target + * Info and status are called to get params string, which is target * specific. When dm_table_status_ioctl is called with flag * DM_STATUS_TABLE_FLAG I have to sent params string back. */ + char *(*info)(void *); char *(*status)(void *); int (*strategy)(dm_table_entry_t *, struct buf *); int (*upcall)(dm_table_entry_t *, struct buf *); diff --git a/sys/dev/disk/dm/dm_ioctl.c b/sys/dev/disk/dm/dm_ioctl.c index 52c3cea6d3..6bc9d783ad 100644 --- a/sys/dev/disk/dm/dm_ioctl.c +++ b/sys/dev/disk/dm/dm_ioctl.c @@ -879,14 +879,18 @@ dm_table_status_ioctl(prop_dictionary_t dm_dict) if (flags & DM_STATUS_TABLE_FLAG) { params = table_en->target->status (table_en->target_config); - - if (params != NULL) { - prop_dictionary_set_cstring(target_dict, - DM_TABLE_PARAMS, params); - - kfree(params, M_DM); - } + } else if (table_en->target->info) { + params = table_en->target->info + (table_en->target_config); + } else { + params = NULL; + } + if (params != NULL) { + prop_dictionary_set_cstring(target_dict, + DM_TABLE_PARAMS, params); + kfree(params, M_DM); } + prop_array_add(cmd_array, target_dict); prop_object_release(target_dict); } diff --git a/sys/dev/disk/dm/targets/delay/dm_target_delay.c b/sys/dev/disk/dm/targets/delay/dm_target_delay.c index 80cbc52c60..fe0c263ad5 100644 --- a/sys/dev/disk/dm/targets/delay/dm_target_delay.c +++ b/sys/dev/disk/dm/targets/delay/dm_target_delay.c @@ -166,6 +166,22 @@ _init(struct dm_delay_info *di, char **argv, int id) return 0; } +static char * +dm_target_delay_info(void *target_config) +{ + dm_target_delay_config_t *tdc; + char *params; + + tdc = target_config; + KKASSERT(tdc != NULL); + + params = kmalloc(DM_MAX_PARAMS_SIZE, M_DM, M_WAITOK); + ksnprintf(params, DM_MAX_PARAMS_SIZE, + "%d %d", tdc->read.count, tdc->write.count); + + return params; +} + static char * dm_target_delay_status(void *target_config) { @@ -464,6 +480,7 @@ dmtd_mod_handler(module_t mod, int type, void *unused) dmt->version[2] = 0; strlcpy(dmt->name, "delay", DM_MAX_TYPE_NAME); dmt->init = &dm_target_delay_init; + dmt->info = &dm_target_delay_info; dmt->status = &dm_target_delay_status; dmt->strategy = &dm_target_delay_strategy; dmt->destroy = &dm_target_delay_destroy; -- 2.41.0