diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index b3244fc7..ae2fdc2d 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -42,7 +42,8 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
 	pgpolicies.o debug.o defaults.o uevent.o time-util.o \
 	switchgroup.o uxsock.o print.o alias.o log_pthread.o \
 	log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
-	lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o
+	lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o \
+	udevrule.o
 
 all: $(LIBS)
 
diff --git a/libmultipath/config.h b/libmultipath/config.h
index ffc69b5f..1f8438b7 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -34,6 +34,7 @@ enum mpath_cmds {
 	CMD_REMOVE_WWID,
 	CMD_RESET_WWIDS,
 	CMD_ADD_WWID,
+	CMD_GEN_UDEVRULE,
 };
 
 enum force_reload_types {
diff --git a/libmultipath/udevrule.c b/libmultipath/udevrule.c
new file mode 100644
index 00000000..e927bf9a
--- /dev/null
+++ b/libmultipath/udevrule.c
@@ -0,0 +1,191 @@
+/*
+ * udevrule.c
+ *
+ * Copyright (c) 2017 Guan Junxiong <guanjunxiong@huawei.com>, Huawei
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "vector.h"
+#include "structs.h"
+#include "debug.h"
+#include "uxsock.h"
+#include "file.h"
+#include "udevrule.h"
+
+#define UUID_PREFIX "mpath-"
+#define UUID_PREFIX_LEN 6
+
+static int has_wwid(FILE *f, char *wwid)
+{
+	char buf[LINE_MAX];
+
+	while (fgets(buf, LINE_MAX, f) != NULL) {
+		if (strstr(buf, wwid))
+			return 1;
+	}
+
+	return 0;
+}
+
+static ssize_t get_md_uuid(char *md, char *dm_uuid)
+{
+	int fd;
+	ssize_t size = -1;
+	char devpath[PATH_SIZE];
+
+	if (strlen(md) < 4 || strncmp(md, "dm-", 3)) {
+		condlog(0, "%s: device name should start with \"dm-\"", md);
+		return -EINVAL;
+	}
+	snprintf(devpath, PATH_SIZE, "/sys/devices/virtual/block/%s/dm/uuid",
+			md);
+	fd = open(devpath, O_RDONLY);
+	if (fd < 0) {
+		condlog(4, "attribute '%s' can not be opened: %s",
+			devpath, strerror(errno));
+		return -errno;
+	}
+	size = read(fd, dm_uuid, WWID_SIZE);
+	if (size < 0) {
+		condlog(4, "read from %s failed: %s", devpath, strerror(errno));
+		size = -errno;
+		dm_uuid[0] = '\0';
+	} else {
+		dm_uuid[size] = '\0';
+	}
+
+	if (!strncmp(dm_uuid, UUID_PREFIX, UUID_PREFIX_LEN)) {
+		memmove(dm_uuid, dm_uuid + UUID_PREFIX_LEN,
+			strlen(dm_uuid + UUID_PREFIX_LEN) + 1);
+		size -= UUID_PREFIX_LEN;
+	}
+	close(fd);
+
+	return size;
+}
+
+static int write_udev_rule(int fd, char *kname, char *dm_wwid,
+		char *wwid, char *id_type)
+{
+	int ret;
+	off_t offset;
+	char buf[LINE_MAX];
+
+	ret = snprintf(buf, LINE_MAX,
+		"KERNEL==\"%s\", ENV{DEVTYPE}==\"disk\", ENV{%s}==\"%s\", ENV{%s}=\"%s\"\n",
+		kname, id_type, wwid, id_type, dm_wwid);
+
+	if (ret >= LINE_MAX || ret < 0) {
+		condlog(0, "can't format udev rule for writing (%d) : %s",
+			ret, strerror(errno));
+		return 1;
+	}
+	offset = lseek(fd, 0, SEEK_END);
+	if (offset < 0) {
+		condlog(0, "can't seek to the end of %s: %s",
+			UDEV_RULES_FILE, strerror(errno));
+		return 1;
+	}
+	if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+		condlog(0, "cannot write udev rule to %s: %s",
+			UDEV_RULES_FILE, strerror(errno));
+		if (ftruncate(fd, offset))
+			condlog(0, "cannot truncate failed udev rule line: %s",
+				strerror(errno));
+		return 1;
+	}
+
+	return 0;
+}
+
+static int write_udev_rules(int fd, char *md, char *wwid)
+{
+	int r = 0;
+	char *kname = "sd*[!0-9]|nvme*[0-9]n*[0-9]";
+	char dm_uuid[WWID_SIZE + 1] = {0};
+	ssize_t size;
+
+	size = get_md_uuid(md, dm_uuid);
+	if (size < 1)
+		return 1;
+	r += write_udev_rule(fd, kname, dm_uuid, wwid, "ID_SERIAL");
+	r += write_udev_rule(fd, kname, dm_uuid, wwid, "ID_WWN");
+	r += write_udev_rule(fd, kname, dm_uuid, wwid, "ID_UUID");
+
+	return r;
+}
+
+int gen_udevrules(char *md, char *wwid)
+{
+	int fd, can_write, found, ret = -1;
+	FILE *f;
+
+	if (!wwid) {
+		condlog(0, "the -m option should combined with -n wwid ");
+		return -1;
+	}
+	if (!md) {
+		condlog(0, "the argument for -m option is null");
+		return -1;
+	}
+	fd = open_file(UDEV_RULES_FILE, &can_write,
+			UDEV_RULE_FILE_HEADHER);
+	if (fd < 0)
+		return -1;
+
+	f = fdopen(fd, "r");
+	if (!f) {
+		condlog(0, "can't fdopen %s: %s",
+			UDEV_RULES_FILE, strerror(errno));
+		close(fd);
+		return -1;
+	}
+
+	found = has_wwid(f, wwid);
+	if (found) {
+		condlog(0, "%s has already contained %s",
+			UDEV_RULES_FILE, wwid);
+		goto out;
+	}
+	if (!can_write) {
+		condlog(0, "%s is read-only. Not writable", UDEV_RULES_FILE);
+		goto out;
+	}
+
+	if (fflush(f) != 0) {
+		condlog(0, "cannot fflush %s stream : %s", UDEV_RULES_FILE,
+			strerror(errno));
+		goto out;
+	}
+
+	ret = write_udev_rules(fd, md, wwid);
+	if (ret == 0) {
+		condlog(0, "write %s file OK. You could use \"udevadm control --reload-rules && udevadm trigger\" to apply this change",
+		UDEV_RULES_FILE);
+	}
+out:
+	fclose(f);
+
+	return ret;
+}
diff --git a/libmultipath/udevrule.h b/libmultipath/udevrule.h
new file mode 100644
index 00000000..8823633e
--- /dev/null
+++ b/libmultipath/udevrule.h
@@ -0,0 +1,13 @@
+#ifndef _UDEVRULE_H
+#define _UDEVRULE_H
+
+#define UDEV_RULES_FILE "/etc/udev/rules.d/99-multipath-udev.rules"
+
+#define UDEV_RULE_FILE_HEADHER \
+"# This file was automatically generated by the multipath program\n" \
+"# You can modify it,as long as you keep each rule on a single\n" \
+"# line,and change only the single line by deleting it .\n"
+
+int gen_udevrules(char *md, char *wwid);
+
+#endif /* _UDEVRULE_H */
diff --git a/multipath/main.c b/multipath/main.c
index dede017e..bc9fdb61 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -58,6 +58,7 @@
 #include "wwids.h"
 #include "uxsock.h"
 #include "mpath_cmd.h"
+#include "udevrule.h"
 
 int logsink;
 struct udev *udev;
@@ -107,6 +108,7 @@ usage (char * progname)
 	fprintf (stderr, "  %s -F [-v lvl] [-R num]\n", progname);
 	fprintf (stderr, "  %s -t\n", progname);
 	fprintf (stderr, "  %s -h\n", progname);
+	fprintf (stderr, "  %s -m dm -n wwid\n", progname);
 	fprintf (stderr,
 		"\n"
 		"Where:\n"
@@ -138,6 +140,9 @@ usage (char * progname)
 		"          . 2 default verbosity\n"
 		"          . 3 print debug information\n"
 		"  -R num  number of times to retry removes of in-use devices\n"
+		"  -m dm  specify the multipath device to be coalesced with\n"
+		"  -n wwid the wwid of the device to be coalesced with the multipath device\n"
+		"          . It is the same as unique identifier the path given the uid_attribute\n"
 		"  dev     action limited to:\n"
 		"          . multipath named 'dev' (ex: mpath0) or\n"
 		"          . multipath whose wwid is 'dev' (ex: 60051..)\n"
@@ -514,6 +519,8 @@ main (int argc, char *argv[])
 	char *dev = NULL;
 	struct config *conf;
 	int retries = -1;
+	char *mpathname = NULL;
+	char *wwid = NULL;
 
 	udev = udev_new();
 	logsink = 0;
@@ -522,7 +529,8 @@ main (int argc, char *argv[])
 		exit(1);
 	multipath_conf = conf;
 	conf->retrigger_tries = 0;
-	while ((arg = getopt(argc, argv, ":adchl::FfM:v:p:b:BrR:itquwW")) != EOF ) {
+	while ((arg = getopt(argc, argv,
+		":adchl::FfM:v:p:b:BrR:itquwWm:n:")) != EOF) {
 		switch(arg) {
 		case 1: printf("optarg : %s\n",optarg);
 			break;
@@ -605,6 +613,14 @@ main (int argc, char *argv[])
 		case 'R':
 			retries = atoi(optarg);
 			break;
+		case 'm':
+			cmd = CMD_GEN_UDEVRULE;
+			mpathname = strdup(optarg);
+			break;
+		case 'n':
+			wwid = strdup(optarg);
+			break;
+
 		case ':':
 			fprintf(stderr, "Missing option argument\n");
 			usage(argv[0]);
@@ -680,6 +696,13 @@ main (int argc, char *argv[])
 		condlog(0, "the -c option requires a path to check");
 		goto out;
 	}
+
+	if (cmd == CMD_GEN_UDEVRULE) {
+		if (gen_udevrules(mpathname, wwid))
+			condlog(0, "cannot generate udev rule file");
+		goto out;
+	}
+
 	if (cmd == CMD_VALID_PATH &&
 	    dev_type == DEV_UEVENT) {
 		int fd;
@@ -758,6 +781,10 @@ out_free_config:
 	udev_unref(udev);
 	if (dev)
 		FREE(dev);
+	if (mpathname)
+		free(mpathname);
+	if (wwid)
+		free(wwid);
 #ifdef _DEBUG_
 	dbg_free_final(NULL);
 #endif
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index b9436e52..3297ce05 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -30,6 +30,10 @@ multipath \- Device mapper target autoconfig.
 .IR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|]
 .RB [\| \-R\ \c
 .IR retries \|]
+.RB [\| \-m\ \c
+.IR dm \ \|\c
+.RB \| \-n\ \c
+.IR wwid \|]
 .RB [\| device \|]
 .
 .
@@ -162,6 +166,14 @@ Number of times to retry flushing multipath devices that are in-use. The default
 is \fI0\fR.
 .
 .TP
+.BI \-m " dm"
+Specify the multipath device to be coalesced with.
+.
+.TP
+.BI \-n " wwid"
+The wwid of the device to be coalesced into the multipath device
+.
+.TP
 .BI device
 Update only the devmap specified by
 .IR device ,
