]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Generate 'change' uevents when arrays change in non-obvious ways.
authorNeilBrown <neilb@suse.de>
Tue, 4 Nov 2008 09:50:39 +0000 (20:50 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 4 Nov 2008 09:50:39 +0000 (20:50 +1100)
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 <neilb@suse.de>
Assemble.c
Create.c
Incremental.c
Manage.c
mdadm.h
mdassemble.c
sysfs.c

index 5c5a13e0e57ec51be2b1e1625cc69dd33223cfc3..f801a73e19c53572941d82604ec1b248bae98a9a 100644 (file)
@@ -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;
                }
index 23047c93d9f2bad5b82720140ecfe74c0090e4e6..a66ed0ce2f01e50dd61ff94ee43bd866917f2df7 100644 (file)
--- 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, &param)) {
                                fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
index 1cccdf7cdc95421d6e8ee5e6e3837013d62c9b1c..f0f0c00c30072c0b9598ea48960d2b0985b3b2cc 100644 (file)
@@ -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)
index 6b9825b41b0689065eb19f04afdd5cbb3cfd184d..fea563a6403ee3ab66d085f26f8d840d5b76b1da 100644 (file)
--- 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 8b8208766be92bb97351547909e148926ec4c706..c34efe9b8713bee2cd651bb5b7129e2749e5b420 100644 (file)
--- 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);
index ef5639a62807d161350c62b4b2ac88e4f4b12512..02afc2d46c05b557b2d375f7830e44cbdd5e8680 100644 (file)
@@ -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 00f42ea65722704c14b32e3e888b2a950ea09e83..7f94d5567d95ce2ae036a8595f3104d5b3eb867c 100644 (file)
--- 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)
 {