sys/dev/disk/dm: Don't implement "status" as a subset of "table" [1/2]
authorTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Mon, 19 Oct 2015 12:36:16 +0000 (21:36 +0900)
committerTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Mon, 19 Oct 2015 13:53:22 +0000 (22:53 +0900)
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
sys/dev/disk/dm/dm_ioctl.c
sys/dev/disk/dm/targets/delay/dm_target_delay.c

index 9fdaa7a..6ba418f 100644 (file)
@@ -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 *);
index 52c3cea..6bc9d78 100644 (file)
@@ -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);
        }
index 80cbc52..fe0c263 100644 (file)
@@ -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;