From 975903767837c572971675a7bf6d866d3be5fa56 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 4 Nov 2008 20:50:39 +1100 Subject: [PATCH] Generate 'change' uevents when arrays change in non-obvious ways. When a 'container' gets started, we need udev to notice, but the kernel has no way of knowing that a KOBJ_CHANGE event is needed. So send one directly via the 'uevent' sysfs attribute. Also, uevents don't get generated when md arrays are stopped (prior to 2.6.28) so send 'change' events then too. Signed-off-by: NeilBrown --- Assemble.c | 1 + Create.c | 10 ++++++---- Incremental.c | 7 +++++++ Manage.c | 9 +++++++-- mdadm.h | 1 + mdassemble.c | 4 ++++ sysfs.c | 16 ++++++++++++++++ 7 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Assemble.c b/Assemble.c index 5c5a13e0..f801a73e 100644 --- a/Assemble.c +++ b/Assemble.c @@ -984,6 +984,7 @@ int Assemble(struct supertype *st, char *mddev, info.array.raid_disks); fprintf(stderr, "\n"); } + sysfs_uevent(&info, "change"); close(mdfd); return 0; } diff --git a/Create.c b/Create.c index 23047c93..a66ed0ce 100644 --- a/Create.c +++ b/Create.c @@ -735,11 +735,12 @@ int Create(struct supertype *st, char *mddev, free(infos); st->ss->free_super(st); - /* param is not actually used */ - if (level == LEVEL_CONTAINER) - /* No need to start */ + if (level == LEVEL_CONTAINER) { + /* No need to start. But we should signal udev to + * create links */ + sysfs_uevent(&info, "change"); ; - else if (runstop == 1 || subdevs >= raiddisks) { + } else if (runstop == 1 || subdevs >= raiddisks) { if (st->ss->external) { switch(level) { case LEVEL_LINEAR: @@ -756,6 +757,7 @@ int Create(struct supertype *st, char *mddev, } sysfs_set_safemode(&info, safe_mode_delay); } else { + /* param is not actually used */ mdu_param_t param; if (ioctl(mdfd, RUN_ARRAY, ¶m)) { fprintf(stderr, Name ": RUN_ARRAY failed: %s\n", diff --git a/Incremental.c b/Incremental.c index 1cccdf7c..f0f0c00c 100644 --- a/Incremental.c +++ b/Incremental.c @@ -376,6 +376,7 @@ int Incremental(char *devname, int verbose, int runstop, if (info.array.level == LEVEL_CONTAINER) { /* Try to assemble within the container */ close(mdfd); + sysfs_uevent(&info, "change"); if (verbose >= 0) fprintf(stderr, Name ": container %s now has %d devices\n", @@ -625,9 +626,15 @@ void RebuildMap(void) st->ss->free_super(st); break; } + sysfs_free(sra); } map_write(map); map_free(map); + for (md = mdstat ; md ; md = md->next) { + struct mdinfo *sra = sysfs_read(-1, md->devnum, GET_VERSION); + sysfs_uevent(sra, "change"); + sysfs_free(sra); + } } int IncrementalScan(int verbose) diff --git a/Manage.c b/Manage.c index 6b9825b4..fea563a6 100644 --- a/Manage.c +++ b/Manage.c @@ -195,8 +195,6 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet) */ ping_monitor(mdi->sys_name); } - if (mdi) - sysfs_free(mdi); if (fd >= 0 && ioctl(fd, STOP_ARRAY, NULL)) { if (quiet == 0) { @@ -208,8 +206,15 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet) "process, mounted filesystem " "or active volume group?\n"); } + if (mdi) + sysfs_free(mdi); return 1; } + /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array + * was stopped, so We'll do it here just to be sure. + */ + if (mdi) + sysfs_uevent(mdi, "change"); if (quiet <= 0) fprintf(stderr, Name ": stopped %s\n", devname); diff --git a/mdadm.h b/mdadm.h index 8b820876..c34efe9b 100644 --- a/mdadm.h +++ b/mdadm.h @@ -356,6 +356,7 @@ extern int sysfs_set_str(struct mdinfo *sra, struct mdinfo *dev, char *name, char *val); extern int sysfs_set_num(struct mdinfo *sra, struct mdinfo *dev, char *name, unsigned long long val); +extern int sysfs_uevent(struct mdinfo *sra, char *event); extern int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev, char *name, unsigned long long *val); extern int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms); diff --git a/mdassemble.c b/mdassemble.c index ef5639a6..02afc2d4 100644 --- a/mdassemble.c +++ b/mdassemble.c @@ -74,6 +74,10 @@ int create_mddev(char *dev, char *name, int autof/*unused*/, int trustworthy, { return open_mddev(dev, 0); } +int sysfs_uevent(struct mdinfo *info, char *event) +{ + return 0; +} #endif int map_update(struct map_ent **mpp, int devnum, char *metadata, int *uuid, char *path) diff --git a/sysfs.c b/sysfs.c index 00f42ea6..7f94d556 100644 --- a/sysfs.c +++ b/sysfs.c @@ -405,6 +405,22 @@ int sysfs_set_num(struct mdinfo *sra, struct mdinfo *dev, return sysfs_set_str(sra, dev, name, valstr); } +int sysfs_uevent(struct mdinfo *sra, char *event) +{ + char fname[50]; + int n; + int fd; + + sprintf(fname, "/sys/block/%s/uevent", + sra->sys_name); + fd = open(fname, O_WRONLY); + if (fd < 0) + return -1; + n = write(fd, event, strlen(event)); + close(fd); + return 0; +} + int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev, char *name, unsigned long long *val) { -- 2.39.2