Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: [PATCH] raidframe detachment



On Thu, Jul 23, 2009 at 01:13:03PM -0500, David Young wrote:
> The attached patch gracefully shuts down a raid unit when you detach it
> with 'drvctl -d raid0', or when you shut down the system.  Please review
> and test.

Attached is a new patch that fixes a bug that Greg Oster found.

Dave

-- 
David Young             OJC Technologies
dyoung%ojctech.com@localhost      Urbana, IL * (217) 278-3933
Index: sys/dev/raidframe/rf_netbsdkintf.c
===================================================================
RCS file: /cvsroot/src/sys/dev/raidframe/rf_netbsdkintf.c,v
retrieving revision 1.265
diff -p -u -u -p -r1.265 rf_netbsdkintf.c
--- sys/dev/raidframe/rf_netbsdkintf.c  10 Jun 2009 14:17:13 -0000      1.265
+++ sys/dev/raidframe/rf_netbsdkintf.c  23 Jul 2009 21:25:24 -0000
@@ -260,6 +260,7 @@ struct raid_softc {
 #define RAIDF_INITED   0x01    /* unit has been initialized */
 #define RAIDF_WLABEL   0x02    /* label area is writable */
 #define RAIDF_LABELLING        0x04    /* unit is currently being labelled */
+#define RAIDF_SHUTDOWN 0x08    /* unit is being shutdown */
 #define RAIDF_WANTED   0x40    /* someone is waiting to obtain a lock */
 #define RAIDF_LOCKED   0x80    /* unit is locked */
 
@@ -267,8 +268,9 @@ struct raid_softc {
 int numraid = 0;
 
 extern struct cfdriver raid_cd;
-CFATTACH_DECL_NEW(raid, sizeof(struct raid_softc),
-    raid_match, raid_attach, raid_detach, NULL);
+CFATTACH_DECL3_NEW(raid, sizeof(struct raid_softc),
+    raid_match, raid_attach, raid_detach, NULL, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
 
 /*
  * Allow RAIDOUTSTANDING number of simultaneous IO's to this RAID device.
@@ -305,6 +307,8 @@ static void raidmakedisklabel(struct rai
 static int raidlock(struct raid_softc *);
 static void raidunlock(struct raid_softc *);
 
+static int raid_detach_unlocked(struct raid_softc *);
+
 static void rf_markalldirty(RF_Raid_t *);
 static void rf_set_properties(struct raid_softc *, RF_Raid_t *);
 
@@ -729,6 +733,12 @@ raidopen(dev_t dev, int flags, int fmt,
 
        if ((error = raidlock(rs)) != 0)
                return (error);
+
+       if ((rs->sc_flags & RAIDF_SHUTDOWN) != 0) {
+               error = EBUSY;
+               goto bad;
+       }
+
        lp = rs->sc_dkdev.dk_label;
 
        part = DISKPART(dev);
@@ -797,7 +807,6 @@ int
 raidclose(dev_t dev, int flags, int fmt, struct lwp *l)
 {
        int     unit = raidunit(dev);
-       cfdata_t cf;
        struct raid_softc *rs;
        int     error = 0;
        int     part;
@@ -833,24 +842,10 @@ raidclose(dev_t dev, int flags, int fmt,
 
                rf_update_component_labels(raidPtrs[unit],
                                                 RF_FINAL_COMPONENT_UPDATE);
-               if (doing_shutdown) {
-                       /* last one, and we're going down, so
-                          lights out for this RAID set too. */
-                       error = rf_Shutdown(raidPtrs[unit]);
-
-                       /* It's no longer initialized... */
-                       rs->sc_flags &= ~RAIDF_INITED;
 
-                       /* detach the device */
-                       
-                       cf = device_cfdata(rs->sc_dev);
-                       error = config_detach(rs->sc_dev, DETACH_QUIET);
-                       free(cf, M_RAIDFRAME);
-                       
-                       /* Detach the disk. */
-                       disk_detach(&rs->sc_dkdev);
-                       disk_destroy(&rs->sc_dkdev);
-               }
+               /* If the kernel is shutting down, it will detach
+                * this RAID set soon enough.
+                */
        }
 
        raidunlock(rs);
@@ -964,6 +959,35 @@ raidwrite(dev_t dev, struct uio *uio, in
 
 }
 
+static int
+raid_detach_unlocked(struct raid_softc *rs)
+{
+       int error;
+       RF_Raid_t *raidPtr;
+
+       raidPtr = raidPtrs[device_unit(rs->sc_dev)];
+
+       /*
+        * If somebody has a partition mounted, we shouldn't
+        * shutdown.
+        */
+       if (rs->sc_dkdev.dk_openmask != 0)
+               return EBUSY;
+
+       if ((rs->sc_flags & RAIDF_INITED) == 0)
+               ;       /* not initialized: nothing to do */
+       else if ((error = rf_Shutdown(raidPtr)) != 0)
+               return error;
+       else
+               rs->sc_flags &= ~(RAIDF_INITED|RAIDF_SHUTDOWN);
+
+       /* Detach the disk. */
+       disk_detach(&rs->sc_dkdev);
+       disk_destroy(&rs->sc_dkdev);
+
+       return 0;
+}
+
 int
 raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
 {
@@ -1173,41 +1197,34 @@ raidioctl(dev_t dev, u_long cmd, void *d
                /* shutdown the system */
        case RAIDFRAME_SHUTDOWN:
 
+               part = DISKPART(dev);
+               pmask = (1 << part);
+
                if ((error = raidlock(rs)) != 0)
                        return (error);
 
-               /*
-                * If somebody has a partition mounted, we shouldn't
-                * shutdown.
-                */
-
-               part = DISKPART(dev);
-               pmask = (1 << part);
                if ((rs->sc_dkdev.dk_openmask & ~pmask) ||
                    ((rs->sc_dkdev.dk_bopenmask & pmask) &&
-                       (rs->sc_dkdev.dk_copenmask & pmask))) {
-                       raidunlock(rs);
-                       return (EBUSY);
+                       (rs->sc_dkdev.dk_copenmask & pmask)))
+                       retcode = EBUSY;
+               else {
+                       rs->sc_flags |= RAIDF_SHUTDOWN;
+                       rs->sc_dkdev.dk_copenmask &= ~pmask;
+                       rs->sc_dkdev.dk_bopenmask &= ~pmask;
+                       rs->sc_dkdev.dk_openmask &= ~pmask;
+                       retcode = 0;
                }
 
-               retcode = rf_Shutdown(raidPtr);
+               raidunlock(rs);
 
-               /* It's no longer initialized... */
-               rs->sc_flags &= ~RAIDF_INITED;
+               if (retcode != 0)
+                       return retcode;
 
                /* free the pseudo device attach bits */
 
                cf = device_cfdata(rs->sc_dev);
-               /* XXX this causes us to not return any errors
-                  from the above call to rf_Shutdown() */
-               retcode = config_detach(rs->sc_dev, DETACH_QUIET);
-               free(cf, M_RAIDFRAME);
-
-               /* Detach the disk. */
-               disk_detach(&rs->sc_dkdev);
-               disk_destroy(&rs->sc_dkdev);
-
-               raidunlock(rs);
+               if ((retcode = config_detach(rs->sc_dev, DETACH_QUIET)) == 0)
+                       free(cf, M_RAIDFRAME);
 
                return (retcode);
        case RAIDFRAME_GET_COMPONENT_LABEL:
@@ -3620,12 +3637,17 @@ raid_attach(device_t parent, device_t se
 static int
 raid_detach(device_t self, int flags)
 {
-       struct raid_softc *rs = device_private(self);
+       int error;
+       struct raid_softc *rs = &raid_softc[device_unit(self)];
 
-       if (rs->sc_flags & RAIDF_INITED)
-               return EBUSY;
+       if ((error = raidlock(rs)) != 0)
+               return (error);
 
-       return 0;
+       error = raid_detach_unlocked(rs);
+
+       raidunlock(rs);
+
+       return error;
 }
 
 static void


Home | Main Index | Thread Index | Old Index