if (sysfs_create_link(&rdev->kobj, ko, "block"))
                /* failure here is OK */;
        rdev->sysfs_state = sysfs_get_dirent_safe(rdev->kobj.sd, "state");
+       rdev->sysfs_unack_badblocks =
+               sysfs_get_dirent_safe(rdev->kobj.sd, "unacknowledged_bad_blocks");
+       rdev->sysfs_badblocks =
+               sysfs_get_dirent_safe(rdev->kobj.sd, "bad_blocks");
 
        list_add_rcu(&rdev->same_set, &mddev->disks);
        bd_link_disk_holder(rdev->bdev, mddev->gendisk);
        rdev->mddev = NULL;
        sysfs_remove_link(&rdev->kobj, "block");
        sysfs_put(rdev->sysfs_state);
+       sysfs_put(rdev->sysfs_unack_badblocks);
+       sysfs_put(rdev->sysfs_badblocks);
        rdev->sysfs_state = NULL;
+       rdev->sysfs_unack_badblocks = NULL;
+       rdev->sysfs_badblocks = NULL;
        rdev->badblocks.count = 0;
        /* We need to delay this, otherwise we can deadlock when
         * writing to 'remove' to "dev/state".  We also need
                goto repeat;
        wake_up(&mddev->sb_wait);
        if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
-               sysfs_notify(&mddev->kobj, NULL, "sync_completed");
+               sysfs_notify_dirent_safe(mddev->sysfs_completed);
 
        rdev_for_each(rdev, mddev) {
                if (test_and_clear_bit(FaultRecorded, &rdev->flags))
        mddev_resume(mddev);
        if (!mddev->thread)
                md_update_sb(mddev, 1);
-       sysfs_notify(&mddev->kobj, NULL, "level");
+       sysfs_notify_dirent_safe(mddev->sysfs_level);
        md_new_event(mddev);
        rv = len;
 out_unlock:
                }
                if (err)
                        return err;
-               sysfs_notify(&mddev->kobj, NULL, "degraded");
+               sysfs_notify_dirent_safe(mddev->sysfs_degraded);
        } else {
                if (cmd_match(page, "check"))
                        set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
 
        if (mddev->sysfs_state)
                sysfs_put(mddev->sysfs_state);
+       if (mddev->sysfs_completed)
+               sysfs_put(mddev->sysfs_completed);
+       if (mddev->sysfs_degraded)
+               sysfs_put(mddev->sysfs_degraded);
+       if (mddev->sysfs_level)
+               sysfs_put(mddev->sysfs_level);
+
 
        if (mddev->gendisk)
                del_gendisk(mddev->gendisk);
        if (!error && mddev->kobj.sd) {
                kobject_uevent(&mddev->kobj, KOBJ_ADD);
                mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state");
+               mddev->sysfs_completed = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_completed");
+               mddev->sysfs_degraded = sysfs_get_dirent_safe(mddev->kobj.sd, "degraded");
+               mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level");
        }
        mddev_put(mddev);
        return error;
        kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
        sysfs_notify_dirent_safe(mddev->sysfs_state);
        sysfs_notify_dirent_safe(mddev->sysfs_action);
-       sysfs_notify(&mddev->kobj, NULL, "degraded");
+       sysfs_notify_dirent_safe(mddev->sysfs_degraded);
 out:
        clear_bit(MD_NOT_READY, &mddev->flags);
        return err;
        } else
                mddev->curr_resync = 3; /* no longer delayed */
        mddev->curr_resync_completed = j;
-       sysfs_notify(&mddev->kobj, NULL, "sync_completed");
+       sysfs_notify_dirent_safe(mddev->sysfs_completed);
        md_new_event(mddev);
        update_time = jiffies;
 
                                mddev->recovery_cp = j;
                        update_time = jiffies;
                        set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
-                       sysfs_notify(&mddev->kobj, NULL, "sync_completed");
+                       sysfs_notify_dirent_safe(mddev->sysfs_completed);
                }
 
                while (j >= mddev->resync_max &&
            !test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
            mddev->curr_resync > 3) {
                mddev->curr_resync_completed = mddev->curr_resync;
-               sysfs_notify(&mddev->kobj, NULL, "sync_completed");
+               sysfs_notify_dirent_safe(mddev->sysfs_completed);
        }
        mddev->pers->sync_request(mddev, max_sectors, &skipped);
 
        }
 
        if (removed && mddev->kobj.sd)
-               sysfs_notify(&mddev->kobj, NULL, "degraded");
+               sysfs_notify_dirent_safe(mddev->sysfs_degraded);
 
        if (this && removed)
                goto no_add;
                /* success...*/
                /* activate any spares */
                if (mddev->pers->spare_active(mddev)) {
-                       sysfs_notify(&mddev->kobj, NULL,
-                                    "degraded");
+                       sysfs_notify_dirent_safe(mddev->sysfs_degraded);
                        set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
                }
        }
        if (rv == 0) {
                /* Make sure they get written out promptly */
                if (test_bit(ExternalBbl, &rdev->flags))
-                       sysfs_notify(&rdev->kobj, NULL,
-                                    "unacknowledged_bad_blocks");
+                       sysfs_notify_dirent_safe(rdev->sysfs_unack_badblocks);
                sysfs_notify_dirent_safe(rdev->sysfs_state);
                set_mask_bits(&mddev->sb_flags, 0,
                              BIT(MD_SB_CHANGE_CLEAN) | BIT(MD_SB_CHANGE_PENDING));
                s += rdev->data_offset;
        rv = badblocks_clear(&rdev->badblocks, s, sectors);
        if ((rv == 0) && test_bit(ExternalBbl, &rdev->flags))
-               sysfs_notify(&rdev->kobj, NULL, "bad_blocks");
+               sysfs_notify_dirent_safe(rdev->sysfs_badblocks);
        return rv;
 }
 EXPORT_SYMBOL_GPL(rdev_clear_badblocks);
        if (rdev->recovery_offset == MaxSector &&
            !test_bit(In_sync, &rdev->flags) &&
            mddev->pers->spare_active(mddev))
-               sysfs_notify(&mddev->kobj, NULL, "degraded");
+               sysfs_notify_dirent_safe(mddev->sysfs_degraded);
 
        put_page(swapout);
        return 0;