From d11abe4bd5cad39803726ddff1888674e417bda5 Mon Sep 17 00:00:00 2001
From: Coly Li <colyli@suse.de>
Date: Wed, 31 Jul 2019 13:29:29 +0800
Subject: [PATCH 1/2] mdadm: add --no-devices to avoid component devices detail
 information
Git-commit: d11abe4bd5cad39803726ddff1888674e417bda5
Patch-mainline: mdadm-4.1+
References: bsc#1139709

When people assemble a md raid device with a large number of
component deivces (e.g. 1500 DASD disks), the raid device detail
information generated by 'mdadm --detail --export $devnode' is very
large. It is because the detail information contains information of
all the component disks (even the missing/failed ones).

In such condition, when udev-md-raid-arrays.rules is triggered and
internally calls "mdadm --detail --no-devices --export $devnode",
user may observe systemd error message ""invalid message length". It
is because the following on-stack raw message buffer in systemd code
is not big enough,
        systemd/src/libudev/libudev-monitor.c
        _public_ struct udev_device *udev_monito ...
                struct ucred *cred;
                union {
                        struct udev_monitor_netlink_header nlh;
                        char raw[8192];
                } buf;
Even change size of raw[] from 8KB to larger size, it may still be not
enough for detail message of a md raid device with much larger number of
component devices.

To fix this problem, an extra option '--no-devices' is added (the
original idea is proposed by Neil Brown). When printing detailed
information of a md raid device, if '--no-devices' is specified, then
all component devices information will not be printed, then the output
message size can be restricted to a small number, even with the systemd
only has 8KB on-disk raw buffer, the md raid array udev rules can work
correctly without failure message.

Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
 Detail.c | 24 ++++++++++++++++--------
 ReadMe.c |  1 +
 mdadm.c  |  4 ++++
 mdadm.h  |  2 ++
 4 files changed, 23 insertions(+), 8 deletions(-)

Index: mdadm-4.0/Detail.c
===================================================================
--- mdadm-4.0.orig/Detail.c
+++ mdadm-4.0/Detail.c
@@ -59,7 +59,7 @@ int Detail(char *dev, struct context *c)
 	int fd = open(dev, O_RDONLY);
 	int vers;
 	mdu_array_info_t array;
-	mdu_disk_info_t *disks;
+	mdu_disk_info_t *disks = NULL;
 	int next;
 	int d;
 	time_t atime;
@@ -282,7 +282,7 @@ int Detail(char *dev, struct context *c)
 				putchar('\n');
 			}
 		}
-		if (sra) {
+		if (!c->no_devices && sra) {
 			struct mdinfo *mdi;
 			for (mdi  = sra->devs; mdi; mdi = mdi->next) {
 				char *path =
@@ -632,12 +632,17 @@ This is pretty boring
 			printf("\n\n");
 		}
 
-		if (array.raid_disks)
-			printf("    Number   Major   Minor   RaidDevice State\n");
-		else
-			printf("    Number   Major   Minor   RaidDevice\n");
+		if (!c->no_devices) {
+			if (array.raid_disks)
+				printf("    Number   Major   Minor   RaidDevice State\n");
+			else
+				printf("    Number   Major   Minor   RaidDevice\n");
+		}
 	}
-	free(info);
+
+	/* if --no_devices specified, not print component devices info */
+	if (c->no_devices)
+		goto skip_devices_state;
 
 	for (d= 0; d < max_disks * 2; d++) {
 		char *dv;
@@ -724,6 +729,8 @@ This is pretty boring
 		}
 		if (!c->brief) printf("\n");
 	}
+
+skip_devices_state:
 	if (spares && c->brief && array.raid_disks) printf(" spares=%d", spares);
 	if (c->brief && st && st->sb)
 		st->ss->brief_detail_super(st);
@@ -743,8 +750,9 @@ This is pretty boring
 		    1, avail))
 		rv = 2;
 
-	free(disks);
 out:
+	free(info);
+	free(disks);
 	close(fd);
 	free(subarray);
 	free(avail);
Index: mdadm-4.0/ReadMe.c
===================================================================
--- mdadm-4.0.orig/ReadMe.c
+++ mdadm-4.0/ReadMe.c
@@ -181,6 +181,7 @@ struct option long_options[] = {
 
     /* For Detail/Examine */
     {"brief",	  0, 0, Brief},
+    {"no-devices",0, 0, NoDevices},
     {"export",	  0, 0, 'Y'},
     {"sparc2.2",  0, 0, Sparc22},
     {"test",      0, 0, 't'},
Index: mdadm-4.0/mdadm.c
===================================================================
--- mdadm-4.0.orig/mdadm.c
+++ mdadm-4.0/mdadm.c
@@ -154,6 +154,10 @@ int main(int argc, char *argv[])
 			c.brief = 1;
 			continue;
 
+		case NoDevices:
+			c.no_devices = 1;
+			continue;
+
 		case 'Y': c.export++;
 			continue;
 
Index: mdadm-4.0/mdadm.h
===================================================================
--- mdadm-4.0.orig/mdadm.h
+++ mdadm-4.0/mdadm.h
@@ -402,6 +402,7 @@ enum special_options {
 	NoSharing,
 	HelpOptions,
 	Brief,
+	NoDevices,
 	ManageOpt,
 	Add,
 	AddSpare,
@@ -512,6 +513,7 @@ struct context {
 	int	runstop;
 	int	verbose;
 	int	brief;
+	int	no_devices;
 	int	force;
 	char	*homehost;
 	int	require_homehost;
