diff -pruN 2:8.4.4-1/debian/changelog 2:8.4.4-1ubuntu1/debian/changelog
--- 2:8.4.4-1/debian/changelog	2013-11-13 12:07:32.000000000 +0000
+++ 2:8.4.4-1ubuntu1/debian/changelog	2014-02-14 02:40:33.000000000 +0000
@@ -1,3 +1,9 @@
+drbd8 (2:8.4.4-1ubuntu1) trusty; urgency=medium
+
+  * debian/patches/ppc64el-ftbfs.patch: Fix build failure on ppc64el.
+
+ -- Steve Langasek <steve.langasek@ubuntu.com>  Thu, 13 Feb 2014 18:40:32 -0800
+
 drbd8 (2:8.4.4-1) unstable; urgency=low
 
   * New upstream version (Closes: #714210, #721443, #711781)
diff -pruN 2:8.4.4-1/debian/control 2:8.4.4-1ubuntu1/debian/control
--- 2:8.4.4-1/debian/control	2013-11-13 12:07:32.000000000 +0000
+++ 2:8.4.4-1ubuntu1/debian/control	2014-02-14 02:43:11.000000000 +0000
@@ -1,7 +1,8 @@
 Source: drbd8
 Section: admin
 Priority: extra
-Maintainer: Debian DRBD Maintainers <debian-ha-maintainers@lists.alioth.debian.org>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Debian DRBD Maintainers <debian-ha-maintainers@lists.alioth.debian.org>
 Uploaders: Norbert Tretkowski <norbert@tretkowski.de>,
  Martin Loschwitz <madkiss@debian.org>,
  Philipp Hug <debian@hug.cx>,
diff -pruN 2:8.4.4-1/debian/patches/ppc64el-ftbfs.patch 2:8.4.4-1ubuntu1/debian/patches/ppc64el-ftbfs.patch
--- 2:8.4.4-1/debian/patches/ppc64el-ftbfs.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2:8.4.4-1ubuntu1/debian/patches/ppc64el-ftbfs.patch	2014-02-14 02:40:25.000000000 +0000
@@ -0,0 +1,27 @@
+Author: Steve Langasek <steve.langasek@ubuntu.com>
+Description: Fix build failure on ppc64el
+ Different glibc headers on powerpc require some additional explicit
+ includes, that aren't included elsewhere.
+
+Index: drbd8-8.4.4/user/config_flags.c
+===================================================================
+--- drbd8-8.4.4.orig/user/config_flags.c
++++ drbd8-8.4.4/user/config_flags.c
+@@ -1,6 +1,7 @@
+ #include <stdbool.h>
+ #include <string.h>
+ #include <assert.h>
++#include <signal.h>
+ 
+ #include <sys/socket.h>
+ #include <linux/netlink.h>
+Index: drbd8-8.4.4/user/drbd_nla.c
+===================================================================
+--- drbd8-8.4.4.orig/user/drbd_nla.c
++++ drbd8-8.4.4/user/drbd_nla.c
+@@ -1,4 +1,5 @@
+ #include <stdbool.h>
++#include <signal.h>
+ #include "libgenl.h"
+ #include <linux/drbd_genl_api.h>
+ #include "drbd_nla.h"
diff -pruN 2:8.4.4-1/debian/patches/series 2:8.4.4-1ubuntu1/debian/patches/series
--- 2:8.4.4-1/debian/patches/series	2013-11-11 12:54:20.000000000 +0000
+++ 2:8.4.4-1ubuntu1/debian/patches/series	2014-02-14 02:40:58.000000000 +0000
@@ -5,3 +5,4 @@ disable-buildtags
 disable-automatic-user-survey.patch
 0001-drbdsetup-use-lib-drbd-drbdsetup-83.patch
 0002-drbdsetup-delay-exiting-due-to-unknown-commands.patch
+ppc64el-ftbfs.patch
diff -pruN 2:8.4.4-1/.pc/applied-patches 2:8.4.4-1ubuntu1/.pc/applied-patches
--- 2:8.4.4-1/.pc/applied-patches	2014-02-14 04:07:24.484824833 +0000
+++ 2:8.4.4-1ubuntu1/.pc/applied-patches	2014-02-14 04:07:24.732831368 +0000
@@ -5,3 +5,4 @@ disable-buildtags
 disable-automatic-user-survey.patch
 0001-drbdsetup-use-lib-drbd-drbdsetup-83.patch
 0002-drbdsetup-delay-exiting-due-to-unknown-commands.patch
+ppc64el-ftbfs.patch
diff -pruN 2:8.4.4-1/.pc/ppc64el-ftbfs.patch/user/config_flags.c 2:8.4.4-1ubuntu1/.pc/ppc64el-ftbfs.patch/user/config_flags.c
--- 2:8.4.4-1/.pc/ppc64el-ftbfs.patch/user/config_flags.c	1970-01-01 00:00:00.000000000 +0000
+++ 2:8.4.4-1ubuntu1/.pc/ppc64el-ftbfs.patch/user/config_flags.c	2013-09-27 16:31:49.000000000 +0000
@@ -0,0 +1,741 @@
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/genetlink.h>
+
+#include "libgenl.h"
+#include <linux/drbd.h>
+#include <linux/drbd_config.h>
+#include <linux/drbd_genl_api.h>
+#include <linux/drbd_limits.h>
+#include "drbd_nla.h"
+#include <linux/genl_magic_func.h>
+#include "drbdtool_common.h"
+#include "config_flags.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+#define NLA_POLICY(p)									\
+	.nla_policy = p ## _nl_policy,							\
+	.nla_policy_size = ARRAY_SIZE(p ## _nl_policy)
+
+/* ============================================================================================== */
+
+static int enum_string_to_int(const char **map, int size, const char *value,
+			      int (*strcmp)(const char *, const char *))
+{
+	int n;
+
+	if (!value)
+		return -1;
+	for (n = 0; n < size; n++) {
+		if (map[n] && !strcmp(value, map[n]))
+			return n;
+	}
+	return -1;
+}
+
+static bool enum_is_default(struct field_def *field, const char *value)
+{
+	int n;
+
+	n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcmp);
+	return n == field->u.e.def;
+}
+
+static bool enum_is_equal(struct field_def *field, const char *a, const char *b)
+{
+	return !strcmp(a, b);
+}
+
+static int type_of_field(struct context_def *ctx, struct field_def *field)
+{
+	return ctx->nla_policy[__nla_type(field->nla_type)].type;
+}
+
+static int len_of_field(struct context_def *ctx, struct field_def *field)
+{
+	return ctx->nla_policy[__nla_type(field->nla_type)].len;
+}
+
+static const char *get_enum(struct context_def *ctx, struct field_def *field, struct nlattr *nla)
+{
+	int i;
+
+	assert(type_of_field(ctx, field) == NLA_U32);
+	i = nla_get_u32(nla);
+	if (i < 0 || i >= field->u.e.size)
+		return NULL;
+	return field->u.e.map[i];
+}
+
+static bool put_enum(struct context_def *ctx, struct field_def *field,
+		     struct msg_buff *msg, const char *value)
+{
+	int n;
+
+	n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcmp);
+	if (n == -1)
+		return false;
+	assert(type_of_field(ctx, field) == NLA_U32);
+	nla_put_u32(msg, field->nla_type, n);
+	return true;
+}
+
+static int enum_usage(struct field_def *field, char *str, int size)
+{
+	const char** map = field->u.e.map;
+	char sep = '{';
+	int n, len = 0, l;
+
+	l = snprintf(str, size, "[--%s=", field->name);
+	len += l; size -= l;
+	for (n = 0; n < field->u.e.size; n++) {
+		if (!map[n])
+			continue;
+		l = snprintf(str + len, size, "%c%s", sep, map[n]);
+		len += l; size -= l;
+		sep = '|';
+	}
+	assert (sep != '{');
+	l = snprintf(str+len, size, "}]");
+	len += l; size -= l;
+	return len;
+}
+
+static bool enum_is_default_nocase(struct field_def *field, const char *value)
+{
+	int n;
+
+	n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcasecmp);
+	return n == field->u.e.def;
+}
+
+static bool enum_is_equal_nocase(struct field_def *field, const char *a, const char *b)
+{
+	return !strcasecmp(a, b);
+}
+
+static bool put_enum_nocase(struct context_def *ctx, struct field_def *field,
+			    struct msg_buff *msg, const char *value)
+{
+	int n;
+
+	n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcasecmp);
+	if (n == -1)
+		return false;
+	assert(type_of_field(ctx, field) == NLA_U32);
+	nla_put_u32(msg, field->nla_type, n);
+	return true;
+}
+
+static void enum_describe_xml(struct field_def *field)
+{
+	const char **map = field->u.e.map;
+	int n;
+
+	printf("\t<option name=\"%s\" type=\"handler\">\n",
+	       field->name);
+	for (n = 0; n < field->u.e.size; n++) {
+		if (!map[n])
+			continue;
+		printf("\t\t<handler>%s</handler>\n", map[n]);
+	}
+	printf("\t</option>\n");
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+static bool numeric_is_default(struct field_def *field, const char *value)
+{
+	long long l;
+
+	/* FIXME: unsigned long long values are broken. */
+	l = m_strtoll(value, field->u.n.scale);
+	return l == field->u.n.def;
+}
+
+static bool numeric_is_equal(struct field_def *field, const char *a, const char *b)
+{
+	long long la, lb;
+
+	/* FIXME: unsigned long long values are broken. */
+	la = m_strtoll(a, field->u.n.scale);
+	lb = m_strtoll(b, field->u.n.scale);
+	return la == lb;
+}
+
+static const char *get_numeric(struct context_def *ctx, struct field_def *field, struct nlattr *nla)
+{
+	static char buffer[1 + 20 + 2];
+	char scale = field->u.n.scale;
+	unsigned long long l;
+	int n;
+
+	switch(type_of_field(ctx, field)) {
+	case NLA_U8:
+		l = nla_get_u8(nla);
+		break;
+	case NLA_U16:
+		l = nla_get_u16(nla);
+		break;
+	case NLA_U32:
+		l = nla_get_u32(nla);
+		break;
+	case NLA_U64:
+		l = nla_get_u64(nla);
+		break;
+	default:
+		return NULL;
+	}
+
+	if (field->u.n.is_signed) {
+		/* Sign extend.  */
+		switch(type_of_field(ctx, field)) {
+		case NLA_U8:
+			l = (int8_t)l;
+			break;
+		case NLA_U16:
+			l = (int16_t)l;
+			break;
+		case NLA_U32:
+			l = (int32_t)l;
+			break;
+		case NLA_U64:
+			l = (int64_t)l;
+			break;
+		}
+		n = snprintf(buffer, sizeof(buffer), "%lld%c",
+			     l, scale == '1' ? 0 : scale);
+	} else
+		n = snprintf(buffer, sizeof(buffer), "%llu%c",
+			     l, scale == '1' ? 0 : scale);
+
+	assert(n < sizeof(buffer));
+	return buffer;
+}
+
+static bool put_numeric(struct context_def *ctx, struct field_def *field,
+			struct msg_buff *msg, const char *value)
+{
+	long long l;
+
+	/* FIXME: unsigned long long values are broken. */
+	l = m_strtoll(value, field->u.n.scale);
+	switch(type_of_field(ctx, field)) {
+	case NLA_U8:
+		nla_put_u8(msg, field->nla_type, l);
+		break;
+	case NLA_U16:
+		nla_put_u16(msg, field->nla_type, l);
+		break;
+	case NLA_U32:
+		nla_put_u32(msg, field->nla_type, l);
+		break;
+	case NLA_U64:
+		nla_put_u64(msg, field->nla_type, l);
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
+static int numeric_usage(struct field_def *field, char *str, int size)
+{
+        return snprintf(str, size,"[--%s=(%lld ... %lld)]",
+			field->name,
+			field->u.n.min,
+			field->u.n.max);
+}
+
+static void numeric_describe_xml(struct field_def *field)
+{
+	printf("\t<option name=\"%s\" type=\"numeric\">\n"
+	       "\t\t<min>%lld</min>\n"
+	       "\t\t<max>%lld</max>\n"
+	       "\t\t<default>%lld</default>\n"
+	       "\t\t<unit_prefix>%c</unit_prefix>\n",
+	       field->name,
+	       field->u.n.min,
+	       field->u.n.max,
+	       field->u.n.def,
+	       field->u.n.scale);
+	if(field->unit) {
+		printf("\t\t<unit>%s</unit>\n",
+		       field->unit);
+	}
+	printf("\t</option>\n");
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+static int boolean_string_to_int(const char *value)
+{
+	if (!value || !strcmp(value, "yes"))
+		return 1;
+	else if (!strcmp(value, "no"))
+		return 0;
+	else
+		return -1;
+}
+
+static bool boolean_is_default(struct field_def *field, const char *value)
+{
+	int yesno;
+
+	yesno = boolean_string_to_int(value);
+	return yesno == field->u.b.def;
+}
+
+static bool boolean_is_equal(struct field_def *field, const char *a, const char *b)
+{
+	return boolean_string_to_int(a) == boolean_string_to_int(b);
+}
+
+static const char *get_boolean(struct context_def *ctx, struct field_def *field, struct nlattr *nla)
+{
+	int i;
+
+	assert(type_of_field(ctx, field) == NLA_U8);
+	i = nla_get_u8(nla);
+	return i ? "yes" : "no";
+}
+
+static bool put_boolean(struct context_def *ctx, struct field_def *field,
+			struct msg_buff *msg, const char *value)
+{
+	int yesno;
+
+	yesno = boolean_string_to_int(value);
+	if (yesno == -1)
+		return false;
+	assert(type_of_field(ctx, field) == NLA_U8);
+	nla_put_u8(msg, field->nla_type, yesno);
+	return true;
+}
+
+static bool put_flag(struct context_def *ctx, struct field_def *field,
+		     struct msg_buff *msg, const char *value)
+{
+	int yesno;
+
+	yesno = boolean_string_to_int(value);
+	if (yesno == -1)
+		return false;
+	assert(type_of_field(ctx, field) == NLA_U8);
+	if (yesno)
+		nla_put_u8(msg, field->nla_type, yesno);
+	return true;
+}
+
+static int boolean_usage(struct field_def *field, char *str, int size)
+{
+        return snprintf(str, size,"[--%s={yes|no}]",
+			field->name);
+}
+
+static void boolean_describe_xml(struct field_def *field)
+{
+	printf("\t<option name=\"%s\" type=\"boolean\">\n"
+	       "\t\t<default>%s</default>\n"
+	       "\t</option>\n",
+	       field->name,
+	       field->u.b.def ? "yes" : "no");
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+static bool string_is_default(struct field_def *field, const char *value)
+{
+	return value && !strcmp(value, "");
+}
+
+static bool string_is_equal(struct field_def *field, const char *a, const char *b)
+{
+	return !strcmp(a, b);
+}
+
+static const char *get_string(struct context_def *ctx, struct field_def *field, struct nlattr *nla)
+{
+	char *str;
+	int len;
+
+	assert(type_of_field(ctx, field) == NLA_NUL_STRING);
+	str = (char *)nla_data(nla);
+	len = len_of_field(ctx, field);
+	assert(memchr(str, 0, len + 1) != NULL);
+	return str;
+}
+
+static bool put_string(struct context_def *ctx, struct field_def *field,
+		       struct msg_buff *msg, const char *value)
+{
+	assert(type_of_field(ctx, field) == NLA_NUL_STRING);
+	nla_put_string(msg, field->nla_type, value);
+	return true;
+}
+
+static int string_usage(struct field_def *field, char *str, int size)
+{
+        return snprintf(str, size,"[--%s=<str>]",
+			field->name);
+}
+
+static void string_describe_xml(struct field_def *field)
+{
+	printf("\t<option name=\"%s\" type=\"string\">\n"
+	       "\t</option>\n",
+	       field->name);
+}
+
+const char *double_quote_string(const char *str)
+{
+	static char *buffer;
+	const char *s;
+	char *b;
+	int len = 0;
+
+	for (s = str; *s; s++) {
+		if (*s == '\\' || *s == '"')
+			len++;
+		len++;
+	}
+	b = realloc(buffer, len + 3);
+	if (!b)
+		return NULL;
+	buffer = b;
+	*b++ = '"';
+	for (s = str; *s; s++) {
+		if (*s == '\\' || *s == '"')
+			*b++ = '\\';
+		*b++ = *s;
+	}
+	*b++ = '"';
+	*b++ = 0;
+	return buffer;
+}
+
+/* ============================================================================================== */
+
+#define ENUM(f, d)									\
+	.nla_type = T_ ## f,								\
+	.is_default = enum_is_default,							\
+	.is_equal = enum_is_equal,							\
+	.get = get_enum,								\
+	.put = put_enum,								\
+	.usage = enum_usage,								\
+	.describe_xml = enum_describe_xml,						\
+	.u = { .e = {									\
+		.map = f ## _map,							\
+		.size = ARRAY_SIZE(f ## _map),						\
+		.def = DRBD_ ## d ## _DEF } }
+
+#define ENUM_NOCASE(f, d)								\
+	.nla_type = T_ ## f,								\
+	.is_default = enum_is_default_nocase,						\
+	.is_equal = enum_is_equal_nocase,						\
+	.get = get_enum,								\
+	.put = put_enum_nocase,								\
+	.usage = enum_usage,								\
+	.describe_xml = enum_describe_xml,						\
+	.u = { .e = {									\
+		.map = f ## _map,							\
+		.size = ARRAY_SIZE(f ## _map),						\
+		.def = DRBD_ ## d ## _DEF } }
+
+#define NUMERIC(f, d)									\
+	.nla_type = T_ ## f,								\
+	.is_default = numeric_is_default,						\
+	.is_equal = numeric_is_equal,							\
+	.get = get_numeric,								\
+	.put = put_numeric,								\
+	.usage = numeric_usage,								\
+	.describe_xml = numeric_describe_xml,						\
+	.u = { .n = {									\
+		.min = DRBD_ ## d ## _MIN,						\
+		.max = DRBD_ ## d ## _MAX,						\
+		.def = DRBD_ ## d ## _DEF,						\
+		.is_signed = F_ ## f ## _IS_SIGNED,					\
+		.scale = DRBD_ ## d ## _SCALE } }
+
+#define BOOLEAN(f, d)									\
+	.nla_type = T_ ## f,								\
+	.is_default = boolean_is_default,						\
+	.is_equal = boolean_is_equal,							\
+	.get = get_boolean,								\
+	.put = put_boolean,								\
+	.usage = boolean_usage,								\
+	.describe_xml = boolean_describe_xml,						\
+	.u = { .b = {									\
+		.def = DRBD_ ## d ## _DEF } },						\
+	.argument_is_optional = true
+
+#define FLAG(f)										\
+	.nla_type = T_ ## f,								\
+	.is_default = boolean_is_default,						\
+	.is_equal = boolean_is_equal,							\
+	.get = get_boolean,								\
+	.put = put_flag,								\
+	.usage = boolean_usage,								\
+	.describe_xml = boolean_describe_xml,						\
+	.u = { .b = {									\
+		.def = false } },							\
+	.argument_is_optional = true
+
+#define STRING(f)									\
+	.nla_type = T_ ## f,								\
+	.is_default = string_is_default,						\
+	.is_equal = string_is_equal,							\
+	.get = get_string,								\
+	.put = put_string,								\
+	.usage = string_usage,								\
+	.describe_xml = string_describe_xml,						\
+	.needs_double_quoting = true
+
+/* ============================================================================================== */
+
+const char *wire_protocol_map[] = {
+	[DRBD_PROT_A] = "A",
+	[DRBD_PROT_B] = "B",
+	[DRBD_PROT_C] = "C",
+};
+
+const char *on_io_error_map[] = {
+	[EP_PASS_ON] = "pass_on",
+	[EP_CALL_HELPER] = "call-local-io-error",
+	[EP_DETACH] = "detach",
+};
+
+const char *fencing_map[] = {
+	[FP_DONT_CARE] = "dont-care",
+	[FP_RESOURCE] = "resource-only",
+	[FP_STONITH] = "resource-and-stonith",
+};
+
+const char *after_sb_0p_map[] = {
+	[ASB_DISCONNECT] = "disconnect",
+	[ASB_DISCARD_YOUNGER_PRI] = "discard-younger-primary",
+	[ASB_DISCARD_OLDER_PRI] = "discard-older-primary",
+	[ASB_DISCARD_ZERO_CHG] = "discard-zero-changes",
+	[ASB_DISCARD_LEAST_CHG] = "discard-least-changes",
+	[ASB_DISCARD_LOCAL] = "discard-local",
+	[ASB_DISCARD_REMOTE] = "discard-remote",
+};
+
+const char *after_sb_1p_map[] = {
+	[ASB_DISCONNECT] = "disconnect",
+	[ASB_CONSENSUS] = "consensus",
+	[ASB_VIOLENTLY] = "violently-as0p",
+	[ASB_DISCARD_SECONDARY] = "discard-secondary",
+	[ASB_CALL_HELPER] = "call-pri-lost-after-sb",
+};
+
+const char *after_sb_2p_map[] = {
+	[ASB_DISCONNECT] = "disconnect",
+	[ASB_VIOLENTLY] = "violently-as0p",
+	[ASB_CALL_HELPER] = "call-pri-lost-after-sb",
+};
+
+const char *rr_conflict_map[] = {
+	[ASB_DISCONNECT] = "disconnect",
+	[ASB_VIOLENTLY] = "violently",
+	[ASB_CALL_HELPER] = "call-pri-lost",
+};
+
+const char *on_no_data_map[] = {
+	[OND_IO_ERROR]		= "io-error",
+	[OND_SUSPEND_IO]	= "suspend-io",
+};
+
+const char *on_congestion_map[] = {
+	[OC_BLOCK] = "block",
+	[OC_PULL_AHEAD] = "pull-ahead",
+	[OC_DISCONNECT] = "disconnect",
+};
+
+const char *read_balancing_map[] = {
+	[RB_PREFER_LOCAL] = "prefer-local",
+	[RB_PREFER_REMOTE] = "prefer-remote",
+	[RB_ROUND_ROBIN] = "round-robin",
+	[RB_LEAST_PENDING] = "least-pending",
+	[RB_CONGESTED_REMOTE] = "when-congested-remote",
+	[RB_32K_STRIPING] = "32K-striping",
+	[RB_64K_STRIPING] = "64K-striping",
+	[RB_128K_STRIPING] = "128K-striping",
+	[RB_256K_STRIPING] = "256K-striping",
+	[RB_512K_STRIPING] = "512K-striping",
+	[RB_1M_STRIPING] = "1M-striping"
+};
+
+#define CHANGEABLE_DISK_OPTIONS								\
+	{ "on-io-error", ENUM(on_io_error, ON_IO_ERROR) },				\
+	{ "fencing", ENUM(fencing, FENCING) },						\
+	{ "disk-barrier", BOOLEAN(disk_barrier, DISK_BARRIER) },			\
+	{ "disk-flushes", BOOLEAN(disk_flushes, DISK_FLUSHES) },			\
+	{ "disk-drain", BOOLEAN(disk_drain, DISK_DRAIN) },				\
+	{ "md-flushes", BOOLEAN(md_flushes, MD_FLUSHES) },				\
+	{ "resync-rate", NUMERIC(resync_rate, RESYNC_RATE),				\
+          .unit = "bytes/second" },							\
+	{ "resync-after", NUMERIC(resync_after, MINOR_NUMBER) },			\
+	{ "al-extents", NUMERIC(al_extents, AL_EXTENTS) },				\
+	{ "al-updates", BOOLEAN(al_updates, AL_UPDATES) },				\
+	{ "c-plan-ahead", NUMERIC(c_plan_ahead, C_PLAN_AHEAD),				\
+          .unit = "1/10 seconds" },							\
+	{ "c-delay-target", NUMERIC(c_delay_target, C_DELAY_TARGET),			\
+          .unit = "1/10 seconds" },							\
+	{ "c-fill-target", NUMERIC(c_fill_target, C_FILL_TARGET),			\
+          .unit = "bytes" },								\
+	{ "c-max-rate", NUMERIC(c_max_rate, C_MAX_RATE),				\
+          .unit = "bytes/second" },							\
+	{ "c-min-rate", NUMERIC(c_min_rate, C_MIN_RATE),				\
+	  .unit = "bytes/second" },							\
+	{ "disk-timeout", NUMERIC(disk_timeout,	DISK_TIMEOUT),				\
+	  .unit = "1/10 seconds" },							\
+	{ "read-balancing", ENUM(read_balancing, READ_BALANCING) }			\
+
+#define CHANGEABLE_NET_OPTIONS								\
+	{ "protocol", ENUM_NOCASE(wire_protocol, PROTOCOL) },				\
+	{ "timeout", NUMERIC(timeout, TIMEOUT),						\
+          .unit = "1/10 seconds" },							\
+	{ "max-epoch-size", NUMERIC(max_epoch_size, MAX_EPOCH_SIZE) },			\
+	{ "max-buffers", NUMERIC(max_buffers, MAX_BUFFERS) },				\
+	{ "unplug-watermark", NUMERIC(unplug_watermark, UNPLUG_WATERMARK) },		\
+	{ "connect-int", NUMERIC(connect_int, CONNECT_INT),				\
+          .unit = "seconds" },								\
+	{ "ping-int", NUMERIC(ping_int, PING_INT),					\
+          .unit = "seconds" },								\
+	{ "sndbuf-size", NUMERIC(sndbuf_size, SNDBUF_SIZE),				\
+          .unit = "bytes" },								\
+	{ "rcvbuf-size", NUMERIC(rcvbuf_size, RCVBUF_SIZE),				\
+          .unit = "bytes" },								\
+	{ "ko-count", NUMERIC(ko_count, KO_COUNT) },					\
+	{ "allow-two-primaries", BOOLEAN(two_primaries, ALLOW_TWO_PRIMARIES) },		\
+	{ "cram-hmac-alg", STRING(cram_hmac_alg) },					\
+	{ "shared-secret", STRING(shared_secret) },					\
+	{ "after-sb-0pri", ENUM(after_sb_0p, AFTER_SB_0P) },				\
+	{ "after-sb-1pri", ENUM(after_sb_1p, AFTER_SB_1P) },				\
+	{ "after-sb-2pri", ENUM(after_sb_2p, AFTER_SB_2P) },				\
+	{ "always-asbp", BOOLEAN(always_asbp, ALWAYS_ASBP) },				\
+	{ "rr-conflict", ENUM(rr_conflict, RR_CONFLICT) },				\
+	{ "ping-timeout", NUMERIC(ping_timeo, PING_TIMEO),				\
+          .unit = "1/10 seconds" },							\
+	{ "data-integrity-alg", STRING(integrity_alg) },				\
+	{ "tcp-cork", BOOLEAN(tcp_cork, TCP_CORK) },					\
+	{ "on-congestion", ENUM(on_congestion, ON_CONGESTION) },			\
+	{ "congestion-fill", NUMERIC(cong_fill, CONG_FILL),				\
+          .unit = "bytes" },								\
+	{ "congestion-extents", NUMERIC(cong_extents, CONG_EXTENTS) },			\
+	{ "csums-alg", STRING(csums_alg) },						\
+	{ "verify-alg", STRING(verify_alg) },						\
+	{ "use-rle", BOOLEAN(use_rle, USE_RLE) }
+
+struct context_def disk_options_ctx = {
+	NLA_POLICY(disk_conf),
+	.fields = {
+		CHANGEABLE_DISK_OPTIONS,
+		{ } },
+};
+
+struct context_def net_options_ctx = {
+	NLA_POLICY(net_conf),
+	.fields = {
+		CHANGEABLE_NET_OPTIONS,
+		{ } },
+};
+
+struct context_def primary_cmd_ctx = {
+	NLA_POLICY(set_role_parms),
+	.fields = {
+		{ "force", FLAG(assume_uptodate) },
+		{ } },
+};
+
+struct context_def attach_cmd_ctx = {
+	NLA_POLICY(disk_conf),
+	.fields = {
+		{ "size", NUMERIC(disk_size, DISK_SIZE),
+		  .unit = "bytes" },
+		{ "max-bio-bvecs", NUMERIC(max_bio_bvecs, MAX_BIO_BVECS) },
+		CHANGEABLE_DISK_OPTIONS,
+		/* { "*", STRING(backing_dev) }, */
+		/* { "*", STRING(meta_dev) }, */
+		/* { "*", NUMERIC(meta_dev_idx, MINOR_NUMBER) }, */
+		{ } },
+};
+
+struct context_def detach_cmd_ctx = {
+	NLA_POLICY(detach_parms),
+	.fields = {
+		{ "force", FLAG(force_detach) },
+		{ }
+	},
+};
+
+struct context_def connect_cmd_ctx = {
+	NLA_POLICY(net_conf),
+	.fields = {
+		{ "tentative", FLAG(tentative) },
+		{ "discard-my-data", FLAG(discard_my_data) },
+		CHANGEABLE_NET_OPTIONS,
+		{ } },
+};
+
+struct context_def disconnect_cmd_ctx = {
+	NLA_POLICY(disconnect_parms),
+	.fields = {
+		{ "force", FLAG(force_disconnect) },
+		{ } },
+};
+
+struct context_def resize_cmd_ctx = {
+	NLA_POLICY(resize_parms),
+	.fields = {
+		{ "size", NUMERIC(resize_size, DISK_SIZE),
+		  .unit = "bytes" },
+		{ "assume-peer-has-space", FLAG(resize_force) },
+		{ "assume-clean", FLAG(no_resync) },
+		{ "al-stripes", NUMERIC(al_stripes, AL_STRIPES) },
+		{ "al-stripe-size-kB", NUMERIC(al_stripe_size, AL_STRIPE_SIZE) },
+		{ } },
+};
+
+struct context_def resource_options_cmd_ctx = {
+	NLA_POLICY(res_opts),
+	.fields = {
+		{ "cpu-mask", STRING(cpu_mask) },
+		{ "on-no-data-accessible", ENUM(on_no_data, ON_NO_DATA) },
+		{ } },
+};
+
+struct context_def new_current_uuid_cmd_ctx = {
+	NLA_POLICY(new_c_uuid_parms),
+	.fields = {
+		{ "clear-bitmap", FLAG(clear_bm) },
+		{ } },
+};
+
+struct context_def verify_cmd_ctx = {
+	NLA_POLICY(start_ov_parms),
+	.fields = {
+		{ "start", NUMERIC(ov_start_sector, DISK_SIZE),
+		  .unit = "bytes" },
+		{ "stop", NUMERIC(ov_stop_sector, DISK_SIZE),
+		  .unit = "bytes" },
+		{ } },
+};
+
+struct context_def new_minor_cmd_ctx = {
+	NLA_POLICY(drbd_cfg_context),
+	.fields = {
+		/* { "*", STRING(ctx_resource_name) }, */
+		/* { "*", NUMERIC(ctx_volume, >= 0) }, */
+		/* { "*", BINARY(ctx_my_addr) }, */
+		/* { "*", BINARY(ctx_peer_addr) }, */
+		{ } },
+};
diff -pruN 2:8.4.4-1/.pc/ppc64el-ftbfs.patch/user/drbd_nla.c 2:8.4.4-1ubuntu1/.pc/ppc64el-ftbfs.patch/user/drbd_nla.c
--- 2:8.4.4-1/.pc/ppc64el-ftbfs.patch/user/drbd_nla.c	1970-01-01 00:00:00.000000000 +0000
+++ 2:8.4.4-1ubuntu1/.pc/ppc64el-ftbfs.patch/user/drbd_nla.c	2013-09-19 14:22:34.000000000 +0000
@@ -0,0 +1,50 @@
+#include <stdbool.h>
+#include "libgenl.h"
+#include <linux/drbd_genl_api.h>
+#include "drbd_nla.h"
+
+static int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla)
+{
+	struct nlattr *head = nla_data(nla);
+	int len = nla_len(nla);
+	int rem;
+
+	/*
+	 * validate_nla (called from nla_parse_nested) ignores attributes
+	 * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag.
+	 * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY
+	 * flag set also, check and remove that flag before calling
+	 * nla_parse_nested.
+	 */
+
+	nla_for_each_attr(nla, head, len, rem) {
+		if (nla->nla_type & DRBD_GENLA_F_MANDATORY) {
+			nla->nla_type &= ~DRBD_GENLA_F_MANDATORY;
+			if (nla_type(nla) > maxtype)
+				return -EOPNOTSUPP;
+		}
+	}
+	return 0;
+}
+
+int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+			  const struct nla_policy *policy)
+{
+	int err;
+
+	err = drbd_nla_check_mandatory(maxtype, nla);
+	if (!err)
+		err = nla_parse_nested(tb, maxtype, nla, policy);
+
+	return err;
+}
+
+struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype)
+{
+	int err;
+
+	err = drbd_nla_check_mandatory(maxtype, nla);
+	if (err)
+		/* ignore */;
+	return nla_find_nested(nla, attrtype);
+}
diff -pruN 2:8.4.4-1/user/config_flags.c 2:8.4.4-1ubuntu1/user/config_flags.c
--- 2:8.4.4-1/user/config_flags.c	2013-09-27 16:31:49.000000000 +0000
+++ 2:8.4.4-1ubuntu1/user/config_flags.c	2014-02-14 04:07:24.000000000 +0000
@@ -1,6 +1,7 @@
 #include <stdbool.h>
 #include <string.h>
 #include <assert.h>
+#include <signal.h>
 
 #include <sys/socket.h>
 #include <linux/netlink.h>
diff -pruN 2:8.4.4-1/user/drbd_nla.c 2:8.4.4-1ubuntu1/user/drbd_nla.c
--- 2:8.4.4-1/user/drbd_nla.c	2013-09-19 14:22:34.000000000 +0000
+++ 2:8.4.4-1ubuntu1/user/drbd_nla.c	2014-02-14 04:07:24.000000000 +0000
@@ -1,4 +1,5 @@
 #include <stdbool.h>
+#include <signal.h>
 #include "libgenl.h"
 #include <linux/drbd_genl_api.h>
 #include "drbd_nla.h"
