diff --git a/libmultipath/config.c b/libmultipath/config.c
index 9d90f512..e6024955 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -464,6 +464,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
 	merge_num(ghost_delay);
 	merge_num(all_tg_pt);
 	merge_num(recheck_wwid);
+	merge_num(auto_resize);
 	merge_num(vpd_vendor_id);
 	merge_num(san_path_err_threshold);
 	merge_num(san_path_err_forget_rate);
@@ -519,6 +520,7 @@ merge_mpe(struct mpentry *dst, struct mpentry *src)
 	merge_num(skip_kpartx);
 	merge_num(max_sectors_kb);
 	merge_num(ghost_delay);
+	merge_num(auto_resize);
 	merge_num(uid);
 	merge_num(gid);
 	merge_num(mode);
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 197a567f..3be8e507 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -96,6 +96,7 @@ struct hwentry {
 	int all_tg_pt;
 	int vpd_vendor_id;
 	int recheck_wwid;
+	int auto_resize;
 	char * bl_product;
 
 	vector pctable;
@@ -135,6 +136,7 @@ struct mpentry {
 	int skip_kpartx;
 	int max_sectors_kb;
 	int ghost_delay;
+	int auto_resize;
 	uid_t uid;
 	gid_t gid;
 	mode_t mode;
@@ -204,6 +206,7 @@ struct config {
 	int skip_delegate;
 	unsigned int sequence_nr;
 	int recheck_wwid;
+	int auto_resize;
 
 	char * selector;
 	struct _vector uid_attrs;
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index d8094903..592761b2 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -355,6 +355,7 @@ int setup_map(struct multipath *mpp, char **params, struct vectors *vecs)
 	select_max_sectors_kb(conf, mpp);
 	select_ghost_delay(conf, mpp);
 	select_flush_on_last_del(conf, mpp);
+	select_auto_resize(conf, mpp);
 
 	sysfs_set_scsi_tmo(conf, mpp);
 	marginal_pathgroups = conf->marginal_pathgroups;
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index d01f9712..64b633f2 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -56,6 +56,7 @@
 #define DEFAULT_UNKNOWN_FIND_MULTIPATHS_TIMEOUT 1
 #define DEFAULT_ALL_TG_PT ALL_TG_PT_OFF
 #define DEFAULT_RECHECK_WWID RECHECK_WWID_OFF
+#define DEFAULT_AUTO_RESIZE AUTO_RESIZE_NEVER
 /* Enable no foreign libraries by default */
 #define DEFAULT_ENABLE_FOREIGN "NONE"
 
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index fc438947..037d717c 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -1670,6 +1670,50 @@ declare_hw_snprint(recheck_wwid, print_yes_no_undef)
 
 declare_def_range_handler(uxsock_timeout, DEFAULT_REPLY_TIMEOUT, INT_MAX)
 
+static int
+set_auto_resize(vector strvec, void *ptr, const char *file, int line_nr)
+{
+	char * buff;
+	int *int_ptr = (int *)ptr;
+
+	buff = set_value(strvec);
+	if (!buff)
+		return 1;
+
+	if (strcmp(buff, "never") == 0)
+		*int_ptr = AUTO_RESIZE_NEVER;
+	else if (strcmp(buff, "grow_only") == 0)
+		*int_ptr = AUTO_RESIZE_GROW_ONLY;
+	else if (strcmp(buff, "grow_shrink") == 0)
+		*int_ptr = AUTO_RESIZE_GROW_SHRINK;
+	else
+		condlog(1, "%s line %d, invalid value for %s: \"%s\"",
+			file, line_nr, (char*)VECTOR_SLOT(strvec, 0), buff);
+
+	free(buff);
+	return 0;
+}
+
+int
+print_auto_resize(struct strbuf *buff, long v)
+{
+	if (!v)
+		return 0;
+	return append_strbuf_quoted(buff,
+			v == AUTO_RESIZE_GROW_ONLY ? "grow_only" :
+			v == AUTO_RESIZE_GROW_SHRINK ? "grow_shrink" :
+			"never");
+}
+
+declare_def_handler(auto_resize, set_auto_resize)
+declare_def_snprint(auto_resize, print_auto_resize)
+declare_ovr_handler(auto_resize, set_auto_resize)
+declare_ovr_snprint(auto_resize, print_auto_resize)
+declare_hw_handler(auto_resize, set_auto_resize)
+declare_hw_snprint(auto_resize, print_auto_resize)
+declare_mp_handler(auto_resize, set_auto_resize)
+declare_mp_snprint(auto_resize, print_auto_resize)
+
 static int
 hw_vpd_vendor_handler(struct config *conf, vector strvec, const char *file,
 		      int line_nr)
@@ -2146,6 +2190,7 @@ init_keywords(vector keywords)
 	install_keyword("remove_retries", &def_remove_retries_handler, &snprint_def_remove_retries);
 	install_keyword("max_sectors_kb", &def_max_sectors_kb_handler, &snprint_def_max_sectors_kb);
 	install_keyword("ghost_delay", &def_ghost_delay_handler, &snprint_def_ghost_delay);
+	install_keyword("auto_resize", &def_auto_resize_handler, &snprint_def_auto_resize);
 	install_keyword("find_multipaths_timeout",
 			&def_find_multipaths_timeout_handler,
 			&snprint_def_find_multipaths_timeout);
@@ -2227,6 +2272,7 @@ init_keywords(vector keywords)
 	install_keyword("skip_kpartx", &hw_skip_kpartx_handler, &snprint_hw_skip_kpartx);
 	install_keyword("max_sectors_kb", &hw_max_sectors_kb_handler, &snprint_hw_max_sectors_kb);
 	install_keyword("ghost_delay", &hw_ghost_delay_handler, &snprint_hw_ghost_delay);
+	install_keyword("auto_resize", &hw_auto_resize_handler, &snprint_hw_auto_resize);
 	install_keyword("all_tg_pt", &hw_all_tg_pt_handler, &snprint_hw_all_tg_pt);
 	install_keyword("vpd_vendor", &hw_vpd_vendor_handler, &snprint_hw_vpd_vendor);
 	install_keyword("recheck_wwid", &hw_recheck_wwid_handler, &snprint_hw_recheck_wwid);
@@ -2273,6 +2319,7 @@ init_keywords(vector keywords)
 	install_keyword("skip_kpartx", &ovr_skip_kpartx_handler, &snprint_ovr_skip_kpartx);
 	install_keyword("max_sectors_kb", &ovr_max_sectors_kb_handler, &snprint_ovr_max_sectors_kb);
 	install_keyword("ghost_delay", &ovr_ghost_delay_handler, &snprint_ovr_ghost_delay);
+	install_keyword("auto_resize", &ovr_auto_resize_handler, &snprint_ovr_auto_resize);
 	install_keyword("all_tg_pt", &ovr_all_tg_pt_handler, &snprint_ovr_all_tg_pt);
 	install_keyword("recheck_wwid", &ovr_recheck_wwid_handler, &snprint_ovr_recheck_wwid);
 	install_keyword_multi("protocol", &protocol_handler, NULL);
@@ -2319,5 +2366,6 @@ init_keywords(vector keywords)
 	install_keyword("skip_kpartx", &mp_skip_kpartx_handler, &snprint_mp_skip_kpartx);
 	install_keyword("max_sectors_kb", &mp_max_sectors_kb_handler, &snprint_mp_max_sectors_kb);
 	install_keyword("ghost_delay", &mp_ghost_delay_handler, &snprint_mp_ghost_delay);
+	install_keyword("auto_resize", &mp_auto_resize_handler, &snprint_mp_auto_resize);
 	install_sublevel_end();
 }
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
index 15d9cbac..7e2dfbe0 100644
--- a/libmultipath/dict.h
+++ b/libmultipath/dict.h
@@ -17,4 +17,5 @@ int print_no_path_retry(struct strbuf *buff, long v);
 int print_undef_off_zero(struct strbuf *buff, long v);
 int print_dev_loss(struct strbuf *buff, unsigned long v);
 int print_off_int_undef(struct strbuf *buff, long v);
+int print_auto_resize(struct strbuf *buff, long v);
 #endif /* _DICT_H */
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index ae6aac79..27a8c9b4 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -75,6 +75,7 @@
 		.skip_kpartx   = SKIP_KPARTX_OFF,
 		.max_sectors_kb = MAX_SECTORS_KB_UNDEF,
 		.ghost_delay   = GHOST_DELAY_OFF,
+		.auto_resize   = AUTO_RESIZE_NEVER,
 	},
 #endif
 
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 15abb9e5..2489c00c 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -1423,6 +1423,23 @@ out:
 	return 0;
 }
 
+int select_auto_resize (struct config *conf, struct multipath * mp)
+{
+	const char *origin;
+	STRBUF_ON_STACK(buff);
+
+	mp_set_mpe(auto_resize);
+	mp_set_ovr(auto_resize);
+	mp_set_hwe(auto_resize);
+	mp_set_conf(auto_resize);
+	mp_set_default(auto_resize, DEFAULT_AUTO_RESIZE);
+out:
+	if (print_auto_resize(&buff, mp->auto_resize) != 0)
+		condlog(3, "%s: auto_resize = %s %s", mp->alias,
+			get_strbuf_str(&buff), origin);
+	return 0;
+}
+
 int select_find_multipaths_timeout(struct config *conf, struct path *pp)
 {
 	const char *origin;
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
index 7203509e..e6941190 100644
--- a/libmultipath/propsel.h
+++ b/libmultipath/propsel.h
@@ -38,6 +38,7 @@ int select_marginal_path_err_rate_threshold(struct config *conf, struct multipat
 int select_marginal_path_err_recheck_gap_time(struct config *conf, struct multipath *mp);
 int select_marginal_path_double_failed_time(struct config *conf, struct multipath *mp);
 int select_ghost_delay(struct config *conf, struct multipath * mp);
+int select_auto_resize(struct config *conf, struct multipath * mp);
 void reconcile_features_with_options(const char *id, char **features,
 				     int* no_path_retry,
 				     int *retain_hwhandler);
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index c20e99ce..b75e7778 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -179,6 +179,13 @@ enum queue_mode_states {
 	QUEUE_MODE_RQ,
 };
 
+enum auto_resize_state {
+	AUTO_RESIZE_UNDEF = 0,
+	AUTO_RESIZE_NEVER,
+	AUTO_RESIZE_GROW_ONLY,
+	AUTO_RESIZE_GROW_SHRINK,
+};
+
 #define PROTOCOL_UNSET -1
 
 enum scsi_protocol {
@@ -447,6 +454,7 @@ struct multipath {
 	int ghost_delay;
 	int ghost_delay_tick;
 	int queue_mode;
+	int auto_resize;
 	uid_t uid;
 	gid_t gid;
 	mode_t mode;
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index 41f3927e..c90383cf 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -1333,6 +1333,22 @@ The default is: \fBno\fR
 .
 .
 .TP
+.B auto_resize
+Controls when multipathd will automatically resize a multipath device.  If set
+to \fInever\fR, multipath devices must always be manually resized by either
+running \fBmultipathd resize map <name>\fR or \fRmultipath -r <name>\fR.  If
+set to \fIgrow_only\fR, when multipathd detects that all of a multipath
+device's paths have increased in size, it will automatically grow the multipath
+device to the new size. If set to \fIgrow_shrink\fR, multipathd will also
+automatically shrink the device once it detects all of its paths have decreased
+in size.
+.RS
+.TP
+The default is: \fBnever\fR
+.RE
+.
+.
+.TP
 .B enable_foreign
 Enables or disables foreign libraries (see section
 .I FOREIGN MULTIPATH SUPPORT
diff --git a/multipathd/main.c b/multipathd/main.c
index 3b4c5b09..ac733491 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1633,7 +1633,6 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
 		ro = uevent_get_disk_ro(uev);
 		if (needs_ro_update(mpp, ro)) {
 			condlog(2, "%s: update path write_protect to '%d' (uevent)", uev->kernel, ro);
-
 			if (mpp->wait_for_udev)
 				mpp->wait_for_udev = 2;
 			else {
@@ -1648,6 +1647,29 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
 				}
 			}
 		}
+		if (mpp->auto_resize != AUTO_RESIZE_NEVER &&
+		    !mpp->wait_for_udev) {
+			struct pathgroup *pgp;
+			struct path *pp2;
+			unsigned int i, j;
+			unsigned long long orig_size = mpp->size;
+
+			if (!pp->size || pp->size == mpp->size ||
+                            (pp->size < mpp->size &&
+			     mpp->auto_resize == AUTO_RESIZE_GROW_ONLY))
+				goto out;
+
+			vector_foreach_slot(mpp->pg, pgp, i)
+				vector_foreach_slot (pgp->paths, pp2, j)
+					if (pp2->size && pp2->size != pp->size)
+						goto out;
+			retval = resize_map(mpp, pp->size, vecs);
+			if (retval == 2)
+				condlog(2, "%s: map removed during resize", pp->dev);
+			else if (retval == 0)
+				condlog(2, "%s: resized map from %llu to %llu",
+					mpp->alias, orig_size, pp->size);
+		}
 	}
 out:
 	lock_cleanup_pop(vecs->lock);
