From 4508a7a734b111b8b7e39986237d84acb1168dd0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 20 Mar 2006 17:53:53 +1100 Subject: [PATCH] sysfs: Allow sysfs attribute files to be pollable It works like this: Open the file Read all the contents. Call poll requesting POLLERR or POLLPRI (so select/exceptfds works) When poll returns, close the file and go to top of loop. or lseek to start of file and go back to the 'read'. Events are signaled by an object manager calling sysfs_notify(kobj, dir, attr); If the dir is non-NULL, it is used to find a subdirectory which contains the attribute (presumably created by sysfs_create_group). This has a cost of one int per attribute, one wait_queuehead per kobject, one int per open file. The name "sysfs_notify" may be confused with the inotify functionality. Maybe it would be nice to support inotify for sysfs attributes as well? This patch also uses sysfs_notify to allow /sys/block/md*/md/sync_action to be pollable Signed-off-by: Neil Brown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/md/md.c') diff --git a/drivers/md/md.c b/drivers/md/md.c index 1ed5152db450..434ca39d19c1 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -163,6 +163,7 @@ void md_new_event(mddev_t *mddev) { atomic_inc(&md_event_count); wake_up(&md_event_waiters); + sysfs_notify(&mddev->kobj, NULL, "sync_action"); } EXPORT_SYMBOL_GPL(md_new_event); -- cgit v1.2.2 From 5dc5cf7dd2723430b6df3d91c5b22af49e063622 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 20 Apr 2006 02:43:23 -0700 Subject: [PATCH] md: locking fix - fix mddev_lock() usage bugs in md_attr_show() and md_attr_store(). [they did not anticipate the possibility of getting a signal] - remove mddev_lock_uninterruptible() [unused] Signed-off-by: Ingo Molnar Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/md/md.c') diff --git a/drivers/md/md.c b/drivers/md/md.c index 434ca39d19c1..d7316b829a62 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -279,11 +279,6 @@ static inline int mddev_lock(mddev_t * mddev) return mutex_lock_interruptible(&mddev->reconfig_mutex); } -static inline void mddev_lock_uninterruptible(mddev_t * mddev) -{ - mutex_lock(&mddev->reconfig_mutex); -} - static inline int mddev_trylock(mddev_t * mddev) { return mutex_trylock(&mddev->reconfig_mutex); @@ -2458,9 +2453,11 @@ md_attr_show(struct kobject *kobj, struct attribute *attr, char *page) if (!entry->show) return -EIO; - mddev_lock(mddev); - rv = entry->show(mddev, page); - mddev_unlock(mddev); + rv = mddev_lock(mddev); + if (!rv) { + rv = entry->show(mddev, page); + mddev_unlock(mddev); + } return rv; } @@ -2474,9 +2471,11 @@ md_attr_store(struct kobject *kobj, struct attribute *attr, if (!entry->store) return -EIO; - mddev_lock(mddev); - rv = entry->store(mddev, page, length); - mddev_unlock(mddev); + rv = mddev_lock(mddev); + if (!rv) { + rv = entry->store(mddev, page, length); + mddev_unlock(mddev); + } return rv; } @@ -4341,8 +4340,9 @@ static int md_seq_show(struct seq_file *seq, void *v) return 0; } - if (mddev_lock(mddev)!=0) + if (mddev_lock(mddev) < 0) return -EINTR; + if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) { seq_printf(seq, "%s : %sactive", mdname(mddev), mddev->pers ? "" : "in"); -- cgit v1.2.2 From 2adc7d47c4dbf684e69ee3980c158ff684dc170e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 20 May 2006 14:59:57 -0700 Subject: [PATCH] md: Fix inverted test for 'repair' directive. We should be able to write 'repair' to /sys/block/mdX/md/sync_action, however due to and inverted test, that always given EINVAL. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/md/md.c') diff --git a/drivers/md/md.c b/drivers/md/md.c index d7316b829a62..3ca3cfb03a7e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2252,7 +2252,7 @@ action_store(mddev_t *mddev, const char *page, size_t len) } else { if (cmd_match(page, "check")) set_bit(MD_RECOVERY_CHECK, &mddev->recovery); - else if (cmd_match(page, "repair")) + else if (!cmd_match(page, "repair")) return -EINVAL; set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); set_bit(MD_RECOVERY_SYNC, &mddev->recovery); -- cgit v1.2.2 From c71d48877e6f3d5e3eb22fcaaa612081bce3d089 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Fri, 26 May 2006 10:39:25 +1000 Subject: [PATCH] Unlock md devices when stopping them on reboot. otherwise we get nasty messages about locks not being released. Signed-off-by: Neil Brown Signed-off-by: Linus Torvalds --- drivers/md/md.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/md/md.c') diff --git a/drivers/md/md.c b/drivers/md/md.c index 3ca3cfb03a7e..ec802913f977 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5028,8 +5028,10 @@ static int md_notify_reboot(struct notifier_block *this, printk(KERN_INFO "md: stopping all md devices.\n"); ITERATE_MDDEV(mddev,tmp) - if (mddev_trylock(mddev)) + if (mddev_trylock(mddev)) { do_md_stop (mddev, 1); + mddev_unlock(mddev); + } /* * certain more exotic SCSI devices are known to be * volatile wrt too early system reboots. While the -- cgit v1.2.2 From c331eb04b995ad276a7ece4608326f1db4e137d8 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 30 May 2006 21:27:13 -0700 Subject: [PATCH] md: Fix badness in sysfs_notify caused by md_new_event From: NeilBrown If an error is reported by a drive in a RAID array (which is done via bi_end_io - in interrupt context), we call md_error and md_new_event which calls sysfs_notify. However sysfs_notify grabs a mutex and so cannot be called in interrupt context. This patch just creates a variant of md_new_event which avoids the sysfs call, and uses that. A better fix for later is to arrange for the event to be called from user-context. Note: avoiding the sysfs call isn't a problem as an error will not, by itself, modify the sync_action attribute. (We do still need to wake_up(&md_event_waiters) as an error by itself will modify /proc/mdstat). Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/md/md.c') diff --git a/drivers/md/md.c b/drivers/md/md.c index ec802913f977..f19b874753a9 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -167,6 +167,15 @@ void md_new_event(mddev_t *mddev) } EXPORT_SYMBOL_GPL(md_new_event); +/* Alternate version that can be called from interrupts + * when calling sysfs_notify isn't needed. + */ +void md_new_event_inintr(mddev_t *mddev) +{ + atomic_inc(&md_event_count); + wake_up(&md_event_waiters); +} + /* * Enables to iterate over all existing md arrays * all_mddevs_lock protects this list. @@ -4149,7 +4158,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev) set_bit(MD_RECOVERY_INTR, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); - md_new_event(mddev); + md_new_event_inintr(mddev); } /* seq_file implementation /proc/mdstat */ -- cgit v1.2.2