浏览代码

Make sure all changes to md/array_state are notified.

Changes in md/array_state could be of interest to a monitoring
program.  So make sure all changes trigger a notification.

Exceptions:
   changing active_idle to active is not reported because it
      is frequent and not interesting.
   changing active to active_idle is only reported on arrays
      with externally managed metadata, as it is not interesting
      otherwise.

Signed-off-by: Neil Brown <neilb@suse.de>
Neil Brown 17 年之前
父节点
当前提交
0fd62b861e
共有 2 个文件被更改,包括 29 次插入5 次删除
  1. 5 0
      Documentation/md.txt
  2. 24 5
      drivers/md/md.c

+ 5 - 0
Documentation/md.txt

@@ -236,6 +236,11 @@ All md devices contain:
      writing the word for the desired state, however some states
      writing the word for the desired state, however some states
      cannot be explicitly set, and some transitions are not allowed.
      cannot be explicitly set, and some transitions are not allowed.
 
 
+     Select/poll works on this file.  All changes except between
+     	active_idle and active (which can be frequent and are not
+	very interesting) are notified.  active->active_idle is
+	reported if the metadata is externally managed.
+
      clear
      clear
          No devices, no size, no level
          No devices, no size, no level
          Writing is equivalent to STOP_ARRAY ioctl
          Writing is equivalent to STOP_ARRAY ioctl

+ 24 - 5
drivers/md/md.c

@@ -2716,8 +2716,10 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
 	}
 	}
 	if (err)
 	if (err)
 		return err;
 		return err;
-	else
+	else {
+		sysfs_notify(&mddev->kobj, NULL, "array_state");
 		return len;
 		return len;
+	}
 }
 }
 static struct md_sysfs_entry md_array_state =
 static struct md_sysfs_entry md_array_state =
 __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
 __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
@@ -3408,7 +3410,11 @@ static void md_safemode_timeout(unsigned long data)
 {
 {
 	mddev_t *mddev = (mddev_t *) data;
 	mddev_t *mddev = (mddev_t *) data;
 
 
-	mddev->safemode = 1;
+	if (!atomic_read(&mddev->writes_pending)) {
+		mddev->safemode = 1;
+		if (mddev->external)
+			sysfs_notify(&mddev->kobj, NULL, "array_state");
+	}
 	md_wakeup_thread(mddev->thread);
 	md_wakeup_thread(mddev->thread);
 }
 }
 
 
@@ -3675,6 +3681,7 @@ static int do_md_run(mddev_t * mddev)
 
 
 	mddev->changed = 1;
 	mddev->changed = 1;
 	md_new_event(mddev);
 	md_new_event(mddev);
+	sysfs_notify(&mddev->kobj, NULL, "array_state");
 	kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE);
 	kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE);
 	return 0;
 	return 0;
 }
 }
@@ -3709,6 +3716,8 @@ static int restart_array(mddev_t *mddev)
 		md_wakeup_thread(mddev->thread);
 		md_wakeup_thread(mddev->thread);
 		md_wakeup_thread(mddev->sync_thread);
 		md_wakeup_thread(mddev->sync_thread);
 		err = 0;
 		err = 0;
+		sysfs_notify(&mddev->kobj, NULL, "array_state");
+
 	} else
 	} else
 		err = -EINVAL;
 		err = -EINVAL;
 
 
@@ -3879,6 +3888,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
 			mdname(mddev));
 			mdname(mddev));
 	err = 0;
 	err = 0;
 	md_new_event(mddev);
 	md_new_event(mddev);
+	sysfs_notify(&mddev->kobj, NULL, "array_state");
 out:
 out:
 	return err;
 	return err;
 }
 }
@@ -4876,8 +4886,9 @@ static int md_ioctl(struct inode *inode, struct file *file,
 	    mddev->ro && mddev->pers) {
 	    mddev->ro && mddev->pers) {
 		if (mddev->ro == 2) {
 		if (mddev->ro == 2) {
 			mddev->ro = 0;
 			mddev->ro = 0;
-		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-		md_wakeup_thread(mddev->thread);
+			sysfs_notify(&mddev->kobj, NULL, "array_state");
+			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+			md_wakeup_thread(mddev->thread);
 
 
 		} else {
 		} else {
 			err = -EROFS;
 			err = -EROFS;
@@ -5516,6 +5527,7 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
  */
  */
 void md_write_start(mddev_t *mddev, struct bio *bi)
 void md_write_start(mddev_t *mddev, struct bio *bi)
 {
 {
+	int did_change = 0;
 	if (bio_data_dir(bi) != WRITE)
 	if (bio_data_dir(bi) != WRITE)
 		return;
 		return;
 
 
@@ -5526,6 +5538,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 		md_wakeup_thread(mddev->thread);
 		md_wakeup_thread(mddev->thread);
 		md_wakeup_thread(mddev->sync_thread);
 		md_wakeup_thread(mddev->sync_thread);
+		did_change = 1;
 	}
 	}
 	atomic_inc(&mddev->writes_pending);
 	atomic_inc(&mddev->writes_pending);
 	if (mddev->safemode == 1)
 	if (mddev->safemode == 1)
@@ -5536,10 +5549,12 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
 			mddev->in_sync = 0;
 			mddev->in_sync = 0;
 			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 			md_wakeup_thread(mddev->thread);
 			md_wakeup_thread(mddev->thread);
+			did_change = 1;
 		}
 		}
 		spin_unlock_irq(&mddev->write_lock);
 		spin_unlock_irq(&mddev->write_lock);
-		sysfs_notify(&mddev->kobj, NULL, "array_state");
 	}
 	}
+	if (did_change)
+		sysfs_notify(&mddev->kobj, NULL, "array_state");
 	wait_event(mddev->sb_wait,
 	wait_event(mddev->sb_wait,
 		   !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
 		   !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
 		   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
 		   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
@@ -5991,18 +6006,22 @@ void md_check_recovery(mddev_t *mddev)
 		int spares = 0;
 		int spares = 0;
 
 
 		if (!mddev->external) {
 		if (!mddev->external) {
+			int did_change = 0;
 			spin_lock_irq(&mddev->write_lock);
 			spin_lock_irq(&mddev->write_lock);
 			if (mddev->safemode &&
 			if (mddev->safemode &&
 			    !atomic_read(&mddev->writes_pending) &&
 			    !atomic_read(&mddev->writes_pending) &&
 			    !mddev->in_sync &&
 			    !mddev->in_sync &&
 			    mddev->recovery_cp == MaxSector) {
 			    mddev->recovery_cp == MaxSector) {
 				mddev->in_sync = 1;
 				mddev->in_sync = 1;
+				did_change = 1;
 				if (mddev->persistent)
 				if (mddev->persistent)
 					set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 					set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 			}
 			}
 			if (mddev->safemode == 1)
 			if (mddev->safemode == 1)
 				mddev->safemode = 0;
 				mddev->safemode = 0;
 			spin_unlock_irq(&mddev->write_lock);
 			spin_unlock_irq(&mddev->write_lock);
+			if (did_change)
+				sysfs_notify(&mddev->kobj, NULL, "array_state");
 		}
 		}
 
 
 		if (mddev->flags)
 		if (mddev->flags)