diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-26 19:42:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-26 19:42:18 -0400 |
commit | f8d56f1771e4867acc461146764b4feeb5245669 (patch) | |
tree | 9d4857b72287f3170818b4b883c232e3ffb677af | |
parent | 3d6eadcb5008beca1b289983ffd7771d1e947bac (diff) | |
parent | 92850bbd71228730c80efd491e7427650188d359 (diff) |
Merge branch 'for-linus' of git://neil.brown.name/md
* 'for-linus' of git://neil.brown.name/md:
md: allow extended partitions on md devices.
md: use sysfs_notify_dirent to notify changes to md/dev-xxx/state
md: use sysfs_notify_dirent to notify changes to md/array_state
-rw-r--r-- | drivers/md/md.c | 56 | ||||
-rw-r--r-- | include/linux/raid/md_k.h | 8 |
2 files changed, 40 insertions, 24 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index c1a837ca193c..b4162f6f1b79 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -222,6 +222,9 @@ static void mddev_put(mddev_t *mddev) | |||
222 | list_del(&mddev->all_mddevs); | 222 | list_del(&mddev->all_mddevs); |
223 | spin_unlock(&all_mddevs_lock); | 223 | spin_unlock(&all_mddevs_lock); |
224 | blk_cleanup_queue(mddev->queue); | 224 | blk_cleanup_queue(mddev->queue); |
225 | if (mddev->sysfs_state) | ||
226 | sysfs_put(mddev->sysfs_state); | ||
227 | mddev->sysfs_state = NULL; | ||
225 | kobject_put(&mddev->kobj); | 228 | kobject_put(&mddev->kobj); |
226 | } else | 229 | } else |
227 | spin_unlock(&all_mddevs_lock); | 230 | spin_unlock(&all_mddevs_lock); |
@@ -1459,6 +1462,8 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1459 | kobject_del(&rdev->kobj); | 1462 | kobject_del(&rdev->kobj); |
1460 | goto fail; | 1463 | goto fail; |
1461 | } | 1464 | } |
1465 | rdev->sysfs_state = sysfs_get_dirent(rdev->kobj.sd, "state"); | ||
1466 | |||
1462 | list_add_rcu(&rdev->same_set, &mddev->disks); | 1467 | list_add_rcu(&rdev->same_set, &mddev->disks); |
1463 | bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk); | 1468 | bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk); |
1464 | return 0; | 1469 | return 0; |
@@ -1488,7 +1493,8 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) | |||
1488 | printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); | 1493 | printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); |
1489 | rdev->mddev = NULL; | 1494 | rdev->mddev = NULL; |
1490 | sysfs_remove_link(&rdev->kobj, "block"); | 1495 | sysfs_remove_link(&rdev->kobj, "block"); |
1491 | 1496 | sysfs_put(rdev->sysfs_state); | |
1497 | rdev->sysfs_state = NULL; | ||
1492 | /* We need to delay this, otherwise we can deadlock when | 1498 | /* We need to delay this, otherwise we can deadlock when |
1493 | * writing to 'remove' to "dev/state". We also need | 1499 | * writing to 'remove' to "dev/state". We also need |
1494 | * to delay it due to rcu usage. | 1500 | * to delay it due to rcu usage. |
@@ -1923,8 +1929,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
1923 | 1929 | ||
1924 | err = 0; | 1930 | err = 0; |
1925 | } | 1931 | } |
1926 | if (!err) | 1932 | if (!err && rdev->sysfs_state) |
1927 | sysfs_notify(&rdev->kobj, NULL, "state"); | 1933 | sysfs_notify_dirent(rdev->sysfs_state); |
1928 | return err ? err : len; | 1934 | return err ? err : len; |
1929 | } | 1935 | } |
1930 | static struct rdev_sysfs_entry rdev_state = | 1936 | static struct rdev_sysfs_entry rdev_state = |
@@ -2019,7 +2025,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
2019 | rdev->raid_disk = -1; | 2025 | rdev->raid_disk = -1; |
2020 | return err; | 2026 | return err; |
2021 | } else | 2027 | } else |
2022 | sysfs_notify(&rdev->kobj, NULL, "state"); | 2028 | sysfs_notify_dirent(rdev->sysfs_state); |
2023 | sprintf(nm, "rd%d", rdev->raid_disk); | 2029 | sprintf(nm, "rd%d", rdev->raid_disk); |
2024 | if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm)) | 2030 | if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm)) |
2025 | printk(KERN_WARNING | 2031 | printk(KERN_WARNING |
@@ -2036,7 +2042,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
2036 | clear_bit(Faulty, &rdev->flags); | 2042 | clear_bit(Faulty, &rdev->flags); |
2037 | clear_bit(WriteMostly, &rdev->flags); | 2043 | clear_bit(WriteMostly, &rdev->flags); |
2038 | set_bit(In_sync, &rdev->flags); | 2044 | set_bit(In_sync, &rdev->flags); |
2039 | sysfs_notify(&rdev->kobj, NULL, "state"); | 2045 | sysfs_notify_dirent(rdev->sysfs_state); |
2040 | } | 2046 | } |
2041 | return len; | 2047 | return len; |
2042 | } | 2048 | } |
@@ -2770,7 +2776,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2770 | if (err) | 2776 | if (err) |
2771 | return err; | 2777 | return err; |
2772 | else { | 2778 | else { |
2773 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 2779 | sysfs_notify_dirent(mddev->sysfs_state); |
2774 | return len; | 2780 | return len; |
2775 | } | 2781 | } |
2776 | } | 2782 | } |
@@ -3457,6 +3463,11 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) | |||
3457 | disk->fops = &md_fops; | 3463 | disk->fops = &md_fops; |
3458 | disk->private_data = mddev; | 3464 | disk->private_data = mddev; |
3459 | disk->queue = mddev->queue; | 3465 | disk->queue = mddev->queue; |
3466 | /* Allow extended partitions. This makes the | ||
3467 | * 'mdp' device redundant, but we can really | ||
3468 | * remove it now. | ||
3469 | */ | ||
3470 | disk->flags |= GENHD_FL_EXT_DEVT; | ||
3460 | add_disk(disk); | 3471 | add_disk(disk); |
3461 | mddev->gendisk = disk; | 3472 | mddev->gendisk = disk; |
3462 | error = kobject_init_and_add(&mddev->kobj, &md_ktype, | 3473 | error = kobject_init_and_add(&mddev->kobj, &md_ktype, |
@@ -3465,8 +3476,10 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) | |||
3465 | if (error) | 3476 | if (error) |
3466 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", | 3477 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", |
3467 | disk->disk_name); | 3478 | disk->disk_name); |
3468 | else | 3479 | else { |
3469 | kobject_uevent(&mddev->kobj, KOBJ_ADD); | 3480 | kobject_uevent(&mddev->kobj, KOBJ_ADD); |
3481 | mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state"); | ||
3482 | } | ||
3470 | return NULL; | 3483 | return NULL; |
3471 | } | 3484 | } |
3472 | 3485 | ||
@@ -3477,7 +3490,7 @@ static void md_safemode_timeout(unsigned long data) | |||
3477 | if (!atomic_read(&mddev->writes_pending)) { | 3490 | if (!atomic_read(&mddev->writes_pending)) { |
3478 | mddev->safemode = 1; | 3491 | mddev->safemode = 1; |
3479 | if (mddev->external) | 3492 | if (mddev->external) |
3480 | set_bit(MD_NOTIFY_ARRAY_STATE, &mddev->flags); | 3493 | sysfs_notify_dirent(mddev->sysfs_state); |
3481 | } | 3494 | } |
3482 | md_wakeup_thread(mddev->thread); | 3495 | md_wakeup_thread(mddev->thread); |
3483 | } | 3496 | } |
@@ -3578,7 +3591,7 @@ static int do_md_run(mddev_t * mddev) | |||
3578 | return -EINVAL; | 3591 | return -EINVAL; |
3579 | } | 3592 | } |
3580 | } | 3593 | } |
3581 | sysfs_notify(&rdev->kobj, NULL, "state"); | 3594 | sysfs_notify_dirent(rdev->sysfs_state); |
3582 | } | 3595 | } |
3583 | 3596 | ||
3584 | md_probe(mddev->unit, NULL, NULL); | 3597 | md_probe(mddev->unit, NULL, NULL); |
@@ -3740,7 +3753,7 @@ static int do_md_run(mddev_t * mddev) | |||
3740 | 3753 | ||
3741 | mddev->changed = 1; | 3754 | mddev->changed = 1; |
3742 | md_new_event(mddev); | 3755 | md_new_event(mddev); |
3743 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 3756 | sysfs_notify_dirent(mddev->sysfs_state); |
3744 | sysfs_notify(&mddev->kobj, NULL, "sync_action"); | 3757 | sysfs_notify(&mddev->kobj, NULL, "sync_action"); |
3745 | sysfs_notify(&mddev->kobj, NULL, "degraded"); | 3758 | sysfs_notify(&mddev->kobj, NULL, "degraded"); |
3746 | kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); | 3759 | kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); |
@@ -3767,7 +3780,7 @@ static int restart_array(mddev_t *mddev) | |||
3767 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 3780 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
3768 | md_wakeup_thread(mddev->thread); | 3781 | md_wakeup_thread(mddev->thread); |
3769 | md_wakeup_thread(mddev->sync_thread); | 3782 | md_wakeup_thread(mddev->sync_thread); |
3770 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 3783 | sysfs_notify_dirent(mddev->sysfs_state); |
3771 | return 0; | 3784 | return 0; |
3772 | } | 3785 | } |
3773 | 3786 | ||
@@ -3847,7 +3860,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
3847 | module_put(mddev->pers->owner); | 3860 | module_put(mddev->pers->owner); |
3848 | mddev->pers = NULL; | 3861 | mddev->pers = NULL; |
3849 | /* tell userspace to handle 'inactive' */ | 3862 | /* tell userspace to handle 'inactive' */ |
3850 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 3863 | sysfs_notify_dirent(mddev->sysfs_state); |
3851 | 3864 | ||
3852 | set_capacity(disk, 0); | 3865 | set_capacity(disk, 0); |
3853 | mddev->changed = 1; | 3866 | mddev->changed = 1; |
@@ -3933,7 +3946,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
3933 | mdname(mddev)); | 3946 | mdname(mddev)); |
3934 | err = 0; | 3947 | err = 0; |
3935 | md_new_event(mddev); | 3948 | md_new_event(mddev); |
3936 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 3949 | sysfs_notify_dirent(mddev->sysfs_state); |
3937 | out: | 3950 | out: |
3938 | return err; | 3951 | return err; |
3939 | } | 3952 | } |
@@ -4297,7 +4310,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
4297 | if (err) | 4310 | if (err) |
4298 | export_rdev(rdev); | 4311 | export_rdev(rdev); |
4299 | else | 4312 | else |
4300 | sysfs_notify(&rdev->kobj, NULL, "state"); | 4313 | sysfs_notify_dirent(rdev->sysfs_state); |
4301 | 4314 | ||
4302 | md_update_sb(mddev, 1); | 4315 | md_update_sb(mddev, 1); |
4303 | if (mddev->degraded) | 4316 | if (mddev->degraded) |
@@ -4938,7 +4951,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, | |||
4938 | if (_IOC_TYPE(cmd) == MD_MAJOR && mddev->ro && mddev->pers) { | 4951 | if (_IOC_TYPE(cmd) == MD_MAJOR && mddev->ro && mddev->pers) { |
4939 | if (mddev->ro == 2) { | 4952 | if (mddev->ro == 2) { |
4940 | mddev->ro = 0; | 4953 | mddev->ro = 0; |
4941 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 4954 | sysfs_notify_dirent(mddev->sysfs_state); |
4942 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 4955 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
4943 | md_wakeup_thread(mddev->thread); | 4956 | md_wakeup_thread(mddev->thread); |
4944 | } else { | 4957 | } else { |
@@ -5612,7 +5625,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi) | |||
5612 | spin_unlock_irq(&mddev->write_lock); | 5625 | spin_unlock_irq(&mddev->write_lock); |
5613 | } | 5626 | } |
5614 | if (did_change) | 5627 | if (did_change) |
5615 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 5628 | sysfs_notify_dirent(mddev->sysfs_state); |
5616 | wait_event(mddev->sb_wait, | 5629 | wait_event(mddev->sb_wait, |
5617 | !test_bit(MD_CHANGE_CLEAN, &mddev->flags) && | 5630 | !test_bit(MD_CHANGE_CLEAN, &mddev->flags) && |
5618 | !test_bit(MD_CHANGE_PENDING, &mddev->flags)); | 5631 | !test_bit(MD_CHANGE_PENDING, &mddev->flags)); |
@@ -5655,7 +5668,7 @@ int md_allow_write(mddev_t *mddev) | |||
5655 | mddev->safemode = 1; | 5668 | mddev->safemode = 1; |
5656 | spin_unlock_irq(&mddev->write_lock); | 5669 | spin_unlock_irq(&mddev->write_lock); |
5657 | md_update_sb(mddev, 0); | 5670 | md_update_sb(mddev, 0); |
5658 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 5671 | sysfs_notify_dirent(mddev->sysfs_state); |
5659 | } else | 5672 | } else |
5660 | spin_unlock_irq(&mddev->write_lock); | 5673 | spin_unlock_irq(&mddev->write_lock); |
5661 | 5674 | ||
@@ -6048,9 +6061,6 @@ void md_check_recovery(mddev_t *mddev) | |||
6048 | if (mddev->bitmap) | 6061 | if (mddev->bitmap) |
6049 | bitmap_daemon_work(mddev->bitmap); | 6062 | bitmap_daemon_work(mddev->bitmap); |
6050 | 6063 | ||
6051 | if (test_and_clear_bit(MD_NOTIFY_ARRAY_STATE, &mddev->flags)) | ||
6052 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | ||
6053 | |||
6054 | if (mddev->ro) | 6064 | if (mddev->ro) |
6055 | return; | 6065 | return; |
6056 | 6066 | ||
@@ -6103,7 +6113,7 @@ void md_check_recovery(mddev_t *mddev) | |||
6103 | mddev->safemode = 0; | 6113 | mddev->safemode = 0; |
6104 | spin_unlock_irq(&mddev->write_lock); | 6114 | spin_unlock_irq(&mddev->write_lock); |
6105 | if (did_change) | 6115 | if (did_change) |
6106 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 6116 | sysfs_notify_dirent(mddev->sysfs_state); |
6107 | } | 6117 | } |
6108 | 6118 | ||
6109 | if (mddev->flags) | 6119 | if (mddev->flags) |
@@ -6111,7 +6121,7 @@ void md_check_recovery(mddev_t *mddev) | |||
6111 | 6121 | ||
6112 | rdev_for_each(rdev, rtmp, mddev) | 6122 | rdev_for_each(rdev, rtmp, mddev) |
6113 | if (test_and_clear_bit(StateChanged, &rdev->flags)) | 6123 | if (test_and_clear_bit(StateChanged, &rdev->flags)) |
6114 | sysfs_notify(&rdev->kobj, NULL, "state"); | 6124 | sysfs_notify_dirent(rdev->sysfs_state); |
6115 | 6125 | ||
6116 | 6126 | ||
6117 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && | 6127 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && |
@@ -6221,7 +6231,7 @@ void md_check_recovery(mddev_t *mddev) | |||
6221 | 6231 | ||
6222 | void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev) | 6232 | void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev) |
6223 | { | 6233 | { |
6224 | sysfs_notify(&rdev->kobj, NULL, "state"); | 6234 | sysfs_notify_dirent(rdev->sysfs_state); |
6225 | wait_event_timeout(rdev->blocked_wait, | 6235 | wait_event_timeout(rdev->blocked_wait, |
6226 | !test_bit(Blocked, &rdev->flags), | 6236 | !test_bit(Blocked, &rdev->flags), |
6227 | msecs_to_jiffies(5000)); | 6237 | msecs_to_jiffies(5000)); |
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index c200b9a34aff..8fc909ef6787 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h | |||
@@ -115,6 +115,9 @@ struct mdk_rdev_s | |||
115 | * in superblock. | 115 | * in superblock. |
116 | */ | 116 | */ |
117 | struct work_struct del_work; /* used for delayed sysfs removal */ | 117 | struct work_struct del_work; /* used for delayed sysfs removal */ |
118 | |||
119 | struct sysfs_dirent *sysfs_state; /* handle for 'state' | ||
120 | * sysfs entry */ | ||
118 | }; | 121 | }; |
119 | 122 | ||
120 | struct mddev_s | 123 | struct mddev_s |
@@ -128,7 +131,6 @@ struct mddev_s | |||
128 | #define MD_CHANGE_DEVS 0 /* Some device status has changed */ | 131 | #define MD_CHANGE_DEVS 0 /* Some device status has changed */ |
129 | #define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */ | 132 | #define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */ |
130 | #define MD_CHANGE_PENDING 2 /* superblock update in progress */ | 133 | #define MD_CHANGE_PENDING 2 /* superblock update in progress */ |
131 | #define MD_NOTIFY_ARRAY_STATE 3 /* atomic context wants to notify userspace */ | ||
132 | 134 | ||
133 | int ro; | 135 | int ro; |
134 | 136 | ||
@@ -239,6 +241,10 @@ struct mddev_s | |||
239 | sector_t resync_max; /* resync should pause | 241 | sector_t resync_max; /* resync should pause |
240 | * when it gets here */ | 242 | * when it gets here */ |
241 | 243 | ||
244 | struct sysfs_dirent *sysfs_state; /* handle for 'array_state' | ||
245 | * file in sysfs. | ||
246 | */ | ||
247 | |||
242 | spinlock_t write_lock; | 248 | spinlock_t write_lock; |
243 | wait_queue_head_t sb_wait; /* for waiting on superblock updates */ | 249 | wait_queue_head_t sb_wait; /* for waiting on superblock updates */ |
244 | atomic_t pending_writes; /* number of active superblock writes */ | 250 | atomic_t pending_writes; /* number of active superblock writes */ |