[Drbd-dev] [PATCH 14/16] drbd: conn_khelper() for user mode callbacks for connections

Philipp Reisner philipp.reisner at linbit.com
Fri Sep 2 12:00:46 CEST 2011


Signed-off-by: Philipp Reisner <philipp.reisner at linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg at linbit.com>
---
 drivers/block/drbd/drbd_nl.c |   87 ++++++++++++++++++++++++++++++++---------
 1 files changed, 68 insertions(+), 19 deletions(-)

diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 7389e37..8f427a1 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -285,43 +285,49 @@ static int drbd_adm_finish(struct genl_info *info, int retcode)
 	return 0;
 }
 
-int drbd_khelper(struct drbd_conf *mdev, char *cmd)
+static void setup_khelper_env(struct drbd_tconn *tconn, char **envp)
 {
-	char *envp[] = { "HOME=/",
-			"TERM=linux",
-			"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
-			NULL, /* Will be set to address family */
-			NULL, /* Will be set to address */
-			NULL };
-	char mb[12], af[20], ad[60], *afs;
-	char *argv[] = {usermode_helper, cmd, mb, NULL };
-	struct sib_info sib;
-	int ret;
+	char af[20], ad[60], *afs;
 
-	snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev));
-
-	if (get_net_conf(mdev->tconn)) {
-		switch (((struct sockaddr *)mdev->tconn->net_conf->peer_addr)->sa_family) {
+	if (get_net_conf(tconn)) {
+		switch (((struct sockaddr *)tconn->net_conf->peer_addr)->sa_family) {
 		case AF_INET6:
 			afs = "ipv6";
 			snprintf(ad, 60, "DRBD_PEER_ADDRESS=%pI6",
-				 &((struct sockaddr_in6 *)mdev->tconn->net_conf->peer_addr)->sin6_addr);
+				 &((struct sockaddr_in6 *)tconn->net_conf->peer_addr)->sin6_addr);
 			break;
 		case AF_INET:
 			afs = "ipv4";
 			snprintf(ad, 60, "DRBD_PEER_ADDRESS=%pI4",
-				 &((struct sockaddr_in *)mdev->tconn->net_conf->peer_addr)->sin_addr);
+				 &((struct sockaddr_in *)tconn->net_conf->peer_addr)->sin_addr);
 			break;
 		default:
 			afs = "ssocks";
 			snprintf(ad, 60, "DRBD_PEER_ADDRESS=%pI4",
-				 &((struct sockaddr_in *)mdev->tconn->net_conf->peer_addr)->sin_addr);
+				 &((struct sockaddr_in *)tconn->net_conf->peer_addr)->sin_addr);
 		}
 		snprintf(af, 20, "DRBD_PEER_AF=%s", afs);
 		envp[3]=af;
 		envp[4]=ad;
-		put_net_conf(mdev->tconn);
+		put_net_conf(tconn);
 	}
+}
+
+int drbd_khelper(struct drbd_conf *mdev, char *cmd)
+{
+	char *envp[] = { "HOME=/",
+			"TERM=linux",
+			"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+			NULL, /* Will be set to address family */
+			NULL, /* Will be set to address */
+			NULL };
+	char mb[12];
+	char *argv[] = {usermode_helper, cmd, mb, NULL };
+	struct sib_info sib;
+	int ret;
+
+	snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev));
+	setup_khelper_env(mdev->tconn, envp);
 
 	/* The helper may take some time.
 	 * write out any unsynced meta data changes now */
@@ -350,6 +356,49 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
 	return ret;
 }
 
+static void conn_md_sync(struct drbd_tconn *tconn)
+{
+	struct drbd_conf *mdev;
+	int minor;
+
+	idr_for_each_entry(&tconn->volumes, mdev, minor)
+		drbd_md_sync(mdev);
+}
+
+int conn_khelper(struct drbd_tconn *tconn, char *cmd)
+{
+	char *envp[] = { "HOME=/",
+			"TERM=linux",
+			"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+			NULL, /* Will be set to address family */
+			NULL, /* Will be set to address */
+			NULL };
+	char *argv[] = {usermode_helper, cmd, tconn->name, NULL };
+	int ret;
+
+	setup_khelper_env(tconn, envp);
+	conn_md_sync(tconn);
+
+	conn_info(tconn, "helper command: %s %s %s\n", usermode_helper, cmd, tconn->name);
+	/* TODO: conn_bcast_event() ?? */
+
+	ret = call_usermodehelper(usermode_helper, argv, envp, 1);
+	if (ret)
+		conn_warn(tconn, "helper command: %s %s %s exit code %u (0x%x)\n",
+			  usermode_helper, cmd, tconn->name,
+			  (ret >> 8) & 0xff, ret);
+	else
+		conn_info(tconn, "helper command: %s %s %s exit code %u (0x%x)\n",
+			  usermode_helper, cmd, tconn->name,
+			  (ret >> 8) & 0xff, ret);
+	/* TODO: conn_bcast_event() ?? */
+
+	if (ret < 0) /* Ignore any ERRNOs we got. */
+		ret = 0;
+
+	return ret;
+}
+
 enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev)
 {
 	char *ex_to_string;
-- 
1.7.4.1



More information about the drbd-dev mailing list