Print this page
XXXX don't fail device detach when it's physically removed

@@ -16,15 +16,20 @@
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
+ * Copyright 2018 Nexenta Systems, Inc.
+ */
+
+/*
  * miscellaneous routines for the devfs
  */
 
 #include <sys/types.h>
 #include <sys/param.h>

@@ -401,17 +406,14 @@
         vp->v_type = dmd->ddm_spec_type == S_IFCHR ? VCHR : VBLK;
         vp->v_rdev = dmd->ddm_dev;
         vn_setops(vp, vn_getops(DVTOV(ddv)));
         vn_exists(vp);
 
-        /* increment dev_ref with devi_lock held */
         ASSERT(DEVI_BUSY_OWNED(devi));
-        mutex_enter(&DEVI(devi)->devi_lock);
-        dv->dv_devi = devi;
-        DEVI(devi)->devi_ref++;         /* ndi_hold_devi(dip) */
-        mutex_exit(&DEVI(devi)->devi_lock);
+        ndi_hold_devi(devi);
 
+        dv->dv_devi = devi;
         dv->dv_ino = dv_mkino(devi, vp->v_type, vp->v_rdev);
         dv->dv_nlink = 0;               /* updated on insert */
         dv->dv_dotdot = ddv;
         dv->dv_attrvp = NULLVP;
         dv->dv_attr = NULL;

@@ -1443,14 +1445,30 @@
                 } else {
                         ASSERT((vp->v_type == VCHR) || (vp->v_type == VBLK));
                         ASSERT(dv->dv_nlink == 1);      /* no hard links */
                         mutex_enter(&vp->v_lock);
                         if (vp->v_count > 0) {
+                                /*
+                                 * The file still has references to it.  If
+                                 * DV_DEVI_GONE is *not* specified then a
+                                 * referenced file is considered busy.
+                                 */
+                                if (!(flags & DV_DEVI_GONE)) {
                                 mutex_exit(&vp->v_lock);
                                 goto set_busy;
                         }
+
+                                /*
+                                 * Mark referenced file stale so that DR will
+                                 * succeed even if there are userland opens.
+                                 */
+                                ASSERT(!DV_STALE(dv));
+                                ndi_rele_devi(dv->dv_devi);
+                                DEVI(dv->dv_devi)->devi_gone = 1;
+                                dv->dv_devi = NULL;
                 }
+                }
 
                 /* unlink from directory */
                 dv_unlink(ddv, dv);
 
                 /* drop locks */