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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/devfs/devfs_subr.c
          +++ new/usr/src/uts/common/fs/devfs/devfs_subr.c
↓ open down ↓ 10 lines elided ↑ open up ↑
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
       21 +
  21   22  /*
  22   23   * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  23   24   */
  24   25  
  25   26  /*
       27 + * Copyright 2018 Nexenta Systems, Inc.
       28 + */
       29 +
       30 +/*
  26   31   * miscellaneous routines for the devfs
  27   32   */
  28   33  
  29   34  #include <sys/types.h>
  30   35  #include <sys/param.h>
  31   36  #include <sys/t_lock.h>
  32   37  #include <sys/systm.h>
  33   38  #include <sys/sysmacros.h>
  34   39  #include <sys/user.h>
  35   40  #include <sys/time.h>
↓ open down ↓ 29 lines elided ↑ open up ↑
  65   70  /*
  66   71   * The devfs_clean_key is taken during a devfs_clean operation: it is used to
  67   72   * prevent unnecessary code execution and for detection of potential deadlocks.
  68   73   */
  69   74  uint_t          devfs_clean_key;
  70   75  
  71   76  struct dv_node *dvroot;
  72   77  
  73   78  /* prototype memory vattrs */
  74   79  vattr_t dv_vattr_dir = {
  75      -        AT_TYPE|AT_MODE|AT_UID|AT_GID,          /* va_mask */
       80 +        AT_TYPE|AT_MODE|AT_UID|AT_GID,          /* va_mask */
  76   81          VDIR,                                   /* va_type */
  77   82          DV_DIRMODE_DEFAULT,                     /* va_mode */
  78   83          DV_UID_DEFAULT,                         /* va_uid */
  79   84          DV_GID_DEFAULT,                         /* va_gid */
  80   85          0,                                      /* va_fsid; */
  81   86          0,                                      /* va_nodeid; */
  82   87          0,                                      /* va_nlink; */
  83   88          0,                                      /* va_size; */
  84   89          0,                                      /* va_atime; */
  85   90          0,                                      /* va_mtime; */
↓ open down ↓ 287 lines elided ↑ open up ↑
 373  378  }
 374  379  
 375  380  /*
 376  381   * dv_mknod
 377  382   *
 378  383   * Given a minor node, create a VCHR or VBLK dv_node.
 379  384   * No dv_attrvp is created at this point.
 380  385   */
 381  386  static struct dv_node *
 382  387  dv_mknod(struct dv_node *ddv, dev_info_t *devi, char *nm,
 383      -        struct ddi_minor_data *dmd)
      388 +    struct ddi_minor_data *dmd)
 384  389  {
 385  390          struct dv_node  *dv;
 386  391          struct vnode    *vp;
 387  392          size_t          nmlen;
 388  393  
 389  394          dcmn_err4(("dv_mknod: %s\n", nm));
 390  395  
 391  396          dv = kmem_cache_alloc(dv_node_cache, KM_SLEEP);
 392  397          nmlen = strlen(nm) + 1;
 393  398          dv->dv_name = kmem_alloc(nmlen, KM_SLEEP);
↓ open down ↓ 2 lines elided ↑ open up ↑
 396  401  
 397  402          vp = DVTOV(dv);
 398  403          vn_reinit(vp);
 399  404          vp->v_flag = 0;
 400  405          vp->v_vfsp = DVTOV(ddv)->v_vfsp;
 401  406          vp->v_type = dmd->ddm_spec_type == S_IFCHR ? VCHR : VBLK;
 402  407          vp->v_rdev = dmd->ddm_dev;
 403  408          vn_setops(vp, vn_getops(DVTOV(ddv)));
 404  409          vn_exists(vp);
 405  410  
 406      -        /* increment dev_ref with devi_lock held */
 407  411          ASSERT(DEVI_BUSY_OWNED(devi));
 408      -        mutex_enter(&DEVI(devi)->devi_lock);
 409      -        dv->dv_devi = devi;
 410      -        DEVI(devi)->devi_ref++;         /* ndi_hold_devi(dip) */
 411      -        mutex_exit(&DEVI(devi)->devi_lock);
      412 +        ndi_hold_devi(devi);
 412  413  
      414 +        dv->dv_devi = devi;
 413  415          dv->dv_ino = dv_mkino(devi, vp->v_type, vp->v_rdev);
 414  416          dv->dv_nlink = 0;               /* updated on insert */
 415  417          dv->dv_dotdot = ddv;
 416  418          dv->dv_attrvp = NULLVP;
 417  419          dv->dv_attr = NULL;
 418  420          dv->dv_flags = 0;
 419  421  
 420  422          if (dmd->type == DDM_INTERNAL_PATH)
 421  423                  dv->dv_flags |= DV_INTERNAL;
 422  424          if (dmd->ddm_flags & DM_NO_FSPERM)
↓ open down ↓ 492 lines elided ↑ open up ↑
 915  917  }
 916  918  
 917  919  /*
 918  920   * Given the parent directory node, and a name in it, returns the
 919  921   * named dv_node to the caller (as a vnode).
 920  922   *
 921  923   * (We need pnp and rdir for doing shadow lookups; they can be NULL)
 922  924   */
 923  925  int
 924  926  dv_find(struct dv_node *ddv, char *nm, struct vnode **vpp, struct pathname *pnp,
 925      -        struct vnode *rdir, struct cred *cred, uint_t ndi_flags)
      927 +    struct vnode *rdir, struct cred *cred, uint_t ndi_flags)
 926  928  {
 927  929          extern int isminiroot;  /* see modctl.c */
 928  930  
 929  931          int                     circ;
 930  932          int                     rv = 0, was_busy = 0, nmlen, write_held = 0;
 931  933          struct vnode            *vp;
 932  934          struct dv_node          *dv, *dup;
 933  935          dev_info_t              *pdevi, *devi = NULL;
 934  936          char                    *mnm;
 935  937          struct ddi_minor_data   *dmd;
↓ open down ↓ 502 lines elided ↑ open up ↑
1438 1440                                   */
1439 1441                                  ASSERT(!DV_STALE(dv));
1440 1442                                  ndi_rele_devi(dv->dv_devi);
1441 1443                                  dv->dv_devi = NULL;     /* mark DV_STALE */
1442 1444                          }
1443 1445                  } else {
1444 1446                          ASSERT((vp->v_type == VCHR) || (vp->v_type == VBLK));
1445 1447                          ASSERT(dv->dv_nlink == 1);      /* no hard links */
1446 1448                          mutex_enter(&vp->v_lock);
1447 1449                          if (vp->v_count > 0) {
1448      -                                mutex_exit(&vp->v_lock);
1449      -                                goto set_busy;
     1450 +                                /*
     1451 +                                 * The file still has references to it.  If
     1452 +                                 * DV_DEVI_GONE is *not* specified then a
     1453 +                                 * referenced file is considered busy.
     1454 +                                 */
     1455 +                                if (!(flags & DV_DEVI_GONE)) {
     1456 +                                        mutex_exit(&vp->v_lock);
     1457 +                                        goto set_busy;
     1458 +                                }
     1459 +
     1460 +                                /*
     1461 +                                 * Mark referenced file stale so that DR will
     1462 +                                 * succeed even if there are userland opens.
     1463 +                                 */
     1464 +                                ASSERT(!DV_STALE(dv));
     1465 +                                ndi_rele_devi(dv->dv_devi);
     1466 +                                DEVI(dv->dv_devi)->devi_gone = 1;
     1467 +                                dv->dv_devi = NULL;
1450 1468                          }
1451 1469                  }
1452 1470  
1453 1471                  /* unlink from directory */
1454 1472                  dv_unlink(ddv, dv);
1455 1473  
1456 1474                  /* drop locks */
1457 1475                  mutex_exit(&vp->v_lock);
1458 1476                  if (vp->v_type == VDIR)
1459 1477                          rw_exit(&dv->dv_contents);
↓ open down ↓ 464 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX