Browse Source

Make sure all changes to md/dev-XX/state are notified

The important state change happens during an interrupt
in md_error.  So just set a flag there and call sysfs_notify
later in process context.

Signed-off-by: Neil Brown <neilb@suse.de>
Neil Brown 17 years ago
parent
commit
526647320e
3 changed files with 26 additions and 1 deletions
  1. 10 0
      Documentation/md.txt
  2. 13 1
      drivers/md/md.c
  3. 3 0
      include/linux/raid/md_k.h

+ 10 - 0
Documentation/md.txt

@@ -297,6 +297,10 @@ Each directory contains:
 	      writemostly - device will only be subject to read
 	      writemostly - device will only be subject to read
 		         requests if there are no other options.
 		         requests if there are no other options.
 			 This applies only to raid1 arrays.
 			 This applies only to raid1 arrays.
+	      blocked  - device has failed, metadata is "external",
+	                 and the failure hasn't been acknowledged yet.
+			 Writes that would write to this device if
+			 it were not faulty are blocked.
 	      spare    - device is working, but not a full member.
 	      spare    - device is working, but not a full member.
 			 This includes spares that are in the process
 			 This includes spares that are in the process
 			 of being recovered to
 			 of being recovered to
@@ -306,6 +310,12 @@ Each directory contains:
 	Writing "remove" removes the device from the array.
 	Writing "remove" removes the device from the array.
 	Writing "writemostly" sets the writemostly flag.
 	Writing "writemostly" sets the writemostly flag.
 	Writing "-writemostly" clears the writemostly flag.
 	Writing "-writemostly" clears the writemostly flag.
+	Writing "blocked" sets the "blocked" flag.
+	Writing "-blocked" clear the "blocked" flag and allows writes
+		to complete.
+
+	This file responds to select/poll. Any change to 'faulty'
+	or 'blocked' causes an event.
 
 
       errors
       errors
 	An approximate count of read errors that have been detected on
 	An approximate count of read errors that have been detected on

+ 13 - 1
drivers/md/md.c

@@ -1886,6 +1886,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 
 
 		err = 0;
 		err = 0;
 	}
 	}
+	if (!err)
+		sysfs_notify(&rdev->kobj, NULL, "state");
 	return err ? err : len;
 	return err ? err : len;
 }
 }
 static struct rdev_sysfs_entry rdev_state =
 static struct rdev_sysfs_entry rdev_state =
@@ -1979,7 +1981,8 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 		if (err) {
 		if (err) {
 			rdev->raid_disk = -1;
 			rdev->raid_disk = -1;
 			return err;
 			return err;
-		}
+		} else
+			sysfs_notify(&rdev->kobj, NULL, "state");
 		sprintf(nm, "rd%d", rdev->raid_disk);
 		sprintf(nm, "rd%d", rdev->raid_disk);
 		if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm))
 		if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm))
 			printk(KERN_WARNING
 			printk(KERN_WARNING
@@ -1996,6 +1999,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 		clear_bit(Faulty, &rdev->flags);
 		clear_bit(Faulty, &rdev->flags);
 		clear_bit(WriteMostly, &rdev->flags);
 		clear_bit(WriteMostly, &rdev->flags);
 		set_bit(In_sync, &rdev->flags);
 		set_bit(In_sync, &rdev->flags);
+		sysfs_notify(&rdev->kobj, NULL, "state");
 	}
 	}
 	return len;
 	return len;
 }
 }
@@ -3525,6 +3529,7 @@ static int do_md_run(mddev_t * mddev)
 				return -EINVAL;
 				return -EINVAL;
 			}
 			}
 		}
 		}
+		sysfs_notify(&rdev->kobj, NULL, "state");
 	}
 	}
 
 
 	md_probe(mddev->unit, NULL, NULL);
 	md_probe(mddev->unit, NULL, NULL);
@@ -4256,6 +4261,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
 		}
 		}
 		if (err)
 		if (err)
 			export_rdev(rdev);
 			export_rdev(rdev);
+		else
+			sysfs_notify(&rdev->kobj, NULL, "state");
 
 
 		md_update_sb(mddev, 1);
 		md_update_sb(mddev, 1);
 		if (mddev->degraded)
 		if (mddev->degraded)
@@ -5115,6 +5122,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
 	mddev->pers->error_handler(mddev,rdev);
 	mddev->pers->error_handler(mddev,rdev);
 	if (mddev->degraded)
 	if (mddev->degraded)
 		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+	set_bit(StateChanged, &rdev->flags);
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
 	md_wakeup_thread(mddev->thread);
@@ -6037,6 +6045,10 @@ void md_check_recovery(mddev_t *mddev)
 		if (mddev->flags)
 		if (mddev->flags)
 			md_update_sb(mddev, 0);
 			md_update_sb(mddev, 0);
 
 
+		rdev_for_each(rdev, rtmp, mddev)
+			if (test_and_clear_bit(StateChanged, &rdev->flags))
+				sysfs_notify(&rdev->kobj, NULL, "state");
+
 
 
 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
 		    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
 		    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {

+ 3 - 0
include/linux/raid/md_k.h

@@ -87,6 +87,9 @@ struct mdk_rdev_s
 #define Blocked		8		/* An error occured on an externally
 #define Blocked		8		/* An error occured on an externally
 					 * managed array, don't allow writes
 					 * managed array, don't allow writes
 					 * until it is cleared */
 					 * until it is cleared */
+#define StateChanged	9		/* Faulty or Blocked has changed during
+					 * interrupt, so it needs to be
+					 * notified by the thread */
 	wait_queue_head_t blocked_wait;
 	wait_queue_head_t blocked_wait;
 
 
 	int desc_nr;			/* descriptor index in the superblock */
 	int desc_nr;			/* descriptor index in the superblock */