Author: mav
Date: Fri May 11 13:20:17 2012
New Revision: 235270
URL: http://svn.freebsd.org/changeset/base/235270

Log:
  - Prevent error status leak if write to some of the RAID1/1E volume disks
  failed while write to some other succeeded. Instead mark disk as failed.
  - Make RAID1E less aggressive in failing disks to avoid volume breakage.
  
  MFC after:    2 weeks

Modified:
  head/sys/geom/raid/tr_raid1.c
  head/sys/geom/raid/tr_raid1e.c

Modified: head/sys/geom/raid/tr_raid1.c
==============================================================================
--- head/sys/geom/raid/tr_raid1.c       Fri May 11 13:03:52 2012        
(r235269)
+++ head/sys/geom/raid/tr_raid1.c       Fri May 11 13:20:17 2012        
(r235270)
@@ -894,7 +894,16 @@ rebuild_round_done:
                g_raid_unlock_range(sd->sd_volume, bp->bio_offset,
                    bp->bio_length);
        }
-       error = bp->bio_error;
+       if (pbp->bio_cmd != BIO_READ) {
+               if (pbp->bio_inbed == 1 || pbp->bio_error != 0)
+                       pbp->bio_error = bp->bio_error;
+               if (bp->bio_error != 0) {
+                       G_RAID_LOGREQ(0, bp, "Write failed: failing subdisk.");
+                       g_raid_tr_raid1_fail_disk(sd->sd_softc, sd, 
sd->sd_disk);
+               }
+               error = pbp->bio_error;
+       } else
+               error = bp->bio_error;
        g_destroy_bio(bp);
        if (pbp->bio_children == pbp->bio_inbed) {
                pbp->bio_completed = pbp->bio_length;

Modified: head/sys/geom/raid/tr_raid1e.c
==============================================================================
--- head/sys/geom/raid/tr_raid1e.c      Fri May 11 13:03:52 2012        
(r235269)
+++ head/sys/geom/raid/tr_raid1e.c      Fri May 11 13:20:17 2012        
(r235270)
@@ -338,6 +338,9 @@ static void
 g_raid_tr_raid1e_fail_disk(struct g_raid_softc *sc, struct g_raid_subdisk *sd,
     struct g_raid_disk *disk)
 {
+       struct g_raid_volume *vol;
+
+       vol = sd->sd_volume;
        /*
         * We don't fail the last disk in the pack, since it still has decent
         * data on it and that's better than failing the disk if it is the root
@@ -347,8 +350,12 @@ g_raid_tr_raid1e_fail_disk(struct g_raid
         * the volume that has / on it.  I can't think of a case where we'd
         * want the volume to go away on this kind of event.
         */
-       if (g_raid_nsubdisks(sd->sd_volume, G_RAID_SUBDISK_S_ACTIVE) == 1 &&
-           g_raid_get_subdisk(sd->sd_volume, G_RAID_SUBDISK_S_ACTIVE) == sd)
+       if ((g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE) +
+            g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_RESYNC) +
+            g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_STALE) +
+            g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_UNINITIALIZED) <
+            vol->v_disks_count) &&
+           (sd->sd_state >= G_RAID_SUBDISK_S_UNINITIALIZED))
                return;
        g_raid_fail_disk(sc, sd, disk);
 }
@@ -1113,7 +1120,16 @@ rebuild_round_done:
                G_RAID_LOGREQ(2, bp, "REMAP done %d.", bp->bio_error);
                g_raid_unlock_range(sd->sd_volume, virtual, bp->bio_length);
        }
-       error = bp->bio_error;
+       if (pbp->bio_cmd != BIO_READ) {
+               if (pbp->bio_inbed == 1 || pbp->bio_error != 0)
+                       pbp->bio_error = bp->bio_error;
+               if (bp->bio_error != 0) {
+                       G_RAID_LOGREQ(0, bp, "Write failed: failing subdisk.");
+                       g_raid_tr_raid1e_fail_disk(sd->sd_softc, sd, 
sd->sd_disk);
+               }
+               error = pbp->bio_error;
+       } else
+               error = bp->bio_error;
        g_destroy_bio(bp);
        if (pbp->bio_children == pbp->bio_inbed) {
                pbp->bio_completed = pbp->bio_length;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to