Print this page


Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/dev/sdev_subr.c
          +++ new/usr/src/uts/common/fs/dev/sdev_subr.c
↓ open down ↓ 142 lines elided ↑ open up ↑
 143  143          0,                                      /* va_ctime */
 144  144          0,                                      /* va_rdev */
 145  145          0,                                      /* va_blksize */
 146  146          0,                                      /* va_nblocks */
 147  147          0                                       /* va_vcode */
 148  148  };
 149  149  
 150  150  kmem_cache_t    *sdev_node_cache;       /* sdev_node cache */
 151  151  int             devtype;                /* fstype */
 152  152  
      153 +/* static */
      154 +static struct vnodeops *sdev_get_vop(struct sdev_node *);
      155 +static void sdev_set_no_negcache(struct sdev_node *);
      156 +static fs_operation_def_t *sdev_merge_vtab(const fs_operation_def_t []);
      157 +static void sdev_free_vtab(fs_operation_def_t *);
      158 +
 153  159  static void
 154  160  sdev_prof_free(struct sdev_node *dv)
 155  161  {
 156  162          ASSERT(!SDEV_IS_GLOBAL(dv));
 157  163          nvlist_free(dv->sdev_prof.dev_name);
 158  164          nvlist_free(dv->sdev_prof.dev_map);
 159  165          nvlist_free(dv->sdev_prof.dev_symlink);
 160  166          nvlist_free(dv->sdev_prof.dev_glob_incdir);
 161  167          nvlist_free(dv->sdev_prof.dev_glob_excdir);
 162  168          bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
↓ open down ↓ 137 lines elided ↑ open up ↑
 300  306          dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP);
 301  307  
 302  308          dv->sdev_name = kmem_alloc(nmlen, KM_SLEEP);
 303  309          bcopy(nm, dv->sdev_name, nmlen);
 304  310          dv->sdev_namelen = nmlen - 1;   /* '\0' not included */
 305  311          len = strlen(ddv->sdev_path) + strlen(nm) + 2;
 306  312          dv->sdev_path = kmem_alloc(len, KM_SLEEP);
 307  313          (void) snprintf(dv->sdev_path, len, "%s/%s", ddv->sdev_path, nm);
 308  314          /* overwritten for VLNK nodes */
 309  315          dv->sdev_symlink = NULL;
 310      -        list_link_init(&dv->sdev_plist);
 311  316  
 312  317          vp = SDEVTOV(dv);
 313  318          vn_reinit(vp);
 314  319          vp->v_vfsp = SDEVTOV(ddv)->v_vfsp;
 315  320          if (vap)
 316  321                  vp->v_type = vap->va_type;
 317  322  
 318  323          /*
 319  324           * initialized to the parent's vnodeops.
 320  325           * maybe overwriten for a VDIR
↓ open down ↓ 68 lines elided ↑ open up ↑
 389  394                      (int (*)(const void *, const void *))sdev_compare_nodes,
 390  395                      sizeof (struct sdev_node),
 391  396                      offsetof(struct sdev_node, sdev_avllink));
 392  397          } else if (type == VLNK) {
 393  398                  ASSERT(args);
 394  399                  dv->sdev_nlink = 1;
 395  400                  dv->sdev_symlink = i_ddi_strdup((char *)args, KM_SLEEP);
 396  401          } else {
 397  402                  dv->sdev_nlink = 1;
 398  403          }
 399      -        sdev_plugin_nodeready(dv);
 400  404  
 401  405          if (!(SDEV_IS_GLOBAL(dv))) {
 402  406                  dv->sdev_origin = (struct sdev_node *)args;
 403  407                  dv->sdev_flags &= ~SDEV_PERSIST;
 404  408          }
 405  409  
 406  410          /*
 407  411           * shadow node is created here OR
 408  412           * if failed (indicated by dv->sdev_attrvp == NULL),
 409  413           * created later in sdev_setattr
↓ open down ↓ 76 lines elided ↑ open up ↑
 486  490              sizeof (struct sdev_node),
 487  491              offsetof(struct sdev_node, sdev_avllink));
 488  492  
 489  493          rw_enter(&dv->sdev_contents, RW_WRITER);
 490  494          sdev_set_nodestate(dv, SDEV_READY);
 491  495          rw_exit(&dv->sdev_contents);
 492  496          sdev_nc_node_exists(dv);
 493  497          return (dv);
 494  498  }
 495  499  
 496      -struct sdev_vop_table vtab[] = {
 497      -        { "pts", devpts_vnodeops_tbl, &devpts_vnodeops, devpts_validate,
      500 +/* directory dependent vop table */
      501 +struct sdev_vop_table {
      502 +        char *vt_name;                          /* subdirectory name */
      503 +        const fs_operation_def_t *vt_service;   /* vnodeops table */
      504 +        struct vnodeops *vt_vops;               /* constructed vop */
      505 +        struct vnodeops **vt_global_vops;       /* global container for vop */
      506 +        int (*vt_vtor)(struct sdev_node *);     /* validate sdev_node */
      507 +        int vt_flags;
      508 +};
      509 +
      510 +/*
      511 + * A nice improvement would be to provide a plug-in mechanism
      512 + * for this table instead of a const table.
      513 + */
      514 +static struct sdev_vop_table vtab[] =
      515 +{
      516 +        { "pts", devpts_vnodeops_tbl, NULL, &devpts_vnodeops, devpts_validate,
 498  517          SDEV_DYNAMIC | SDEV_VTOR },
 499  518  
 500      -        { "vt", devvt_vnodeops_tbl, &devvt_vnodeops, devvt_validate,
      519 +        { "vt", devvt_vnodeops_tbl, NULL, &devvt_vnodeops, devvt_validate,
 501  520          SDEV_DYNAMIC | SDEV_VTOR },
 502  521  
 503      -        { "zvol", devzvol_vnodeops_tbl, &devzvol_vnodeops,
      522 +        { "zvol", devzvol_vnodeops_tbl, NULL, &devzvol_vnodeops,
 504  523          devzvol_validate, SDEV_ZONED | SDEV_DYNAMIC | SDEV_VTOR | SDEV_SUBDIR },
 505  524  
 506      -        { "zcons", NULL, NULL, NULL, SDEV_NO_NCACHE },
      525 +        { "zcons", NULL, NULL, NULL, NULL, SDEV_NO_NCACHE },
 507  526  
 508      -        { "net", devnet_vnodeops_tbl, &devnet_vnodeops, devnet_validate,
 509      -        SDEV_DYNAMIC | SDEV_VTOR | SDEV_SUBDIR },
      527 +        { "net", devnet_vnodeops_tbl, NULL, &devnet_vnodeops, devnet_validate,
      528 +        SDEV_DYNAMIC | SDEV_VTOR },
 510  529  
 511      -        { "ipnet", devipnet_vnodeops_tbl, &devipnet_vnodeops,
      530 +        { "ipnet", devipnet_vnodeops_tbl, NULL, &devipnet_vnodeops,
 512  531          devipnet_validate, SDEV_DYNAMIC | SDEV_VTOR | SDEV_NO_NCACHE },
 513  532  
 514  533          /*
 515  534           * SDEV_DYNAMIC: prevent calling out to devfsadm, since only the
 516  535           * lofi driver controls child nodes.
 517  536           *
 518  537           * SDEV_PERSIST: ensure devfsadm knows to clean up any persisted
 519  538           * stale nodes (e.g. from devfsadm -R).
 520  539           *
 521  540           * In addition, devfsadm knows not to attempt a rmdir: a zone
 522  541           * may hold a reference, which would zombify the node,
 523  542           * preventing a mkdir.
 524  543           */
 525  544  
 526      -        { "lofi", NULL, NULL, NULL,
      545 +        { "lofi", NULL, NULL, NULL, NULL,
 527  546              SDEV_ZONED | SDEV_DYNAMIC | SDEV_PERSIST },
 528      -        { "rlofi", NULL, NULL, NULL,
      547 +        { "rlofi", NULL, NULL, NULL, NULL,
 529  548              SDEV_ZONED | SDEV_DYNAMIC | SDEV_PERSIST },
 530  549  
 531      -        { NULL, NULL, NULL, NULL, 0}
      550 +        { NULL, NULL, NULL, NULL, NULL, 0}
 532  551  };
 533  552  
      553 +/*
      554 + * We need to match off of the sdev_path, not the sdev_name. We are only allowed
      555 + * to exist directly under /dev.
      556 + */
      557 +struct sdev_vop_table *
      558 +sdev_match(struct sdev_node *dv)
      559 +{
      560 +        int vlen;
      561 +        int i;
      562 +        const char *path;
 534  563  
      564 +        if (strlen(dv->sdev_path) <= 5)
      565 +                return (NULL);
      566 +
      567 +        if (strncmp(dv->sdev_path, "/dev/", 5) != 0)
      568 +                return (NULL);
      569 +        path = dv->sdev_path + 5;
      570 +
      571 +        for (i = 0; vtab[i].vt_name; i++) {
      572 +                if (strcmp(vtab[i].vt_name, path) == 0)
      573 +                        return (&vtab[i]);
      574 +                if (vtab[i].vt_flags & SDEV_SUBDIR) {
      575 +                        vlen = strlen(vtab[i].vt_name);
      576 +                        if ((strncmp(vtab[i].vt_name, path,
      577 +                            vlen - 1) == 0) && path[vlen] == '/')
      578 +                                return (&vtab[i]);
      579 +                }
      580 +
      581 +        }
      582 +        return (NULL);
      583 +}
      584 +
 535  585  /*
      586 + *  sets a directory's vnodeops if the directory is in the vtab;
      587 + */
      588 +static struct vnodeops *
      589 +sdev_get_vop(struct sdev_node *dv)
      590 +{
      591 +        struct sdev_vop_table *vtp;
      592 +        char *path;
      593 +
      594 +        path = dv->sdev_path;
      595 +        ASSERT(path);
      596 +
      597 +        /* gets the relative path to /dev/ */
      598 +        path += 5;
      599 +
      600 +        /* gets the vtab entry it matches */
      601 +        if ((vtp = sdev_match(dv)) != NULL) {
      602 +                dv->sdev_flags |= vtp->vt_flags;
      603 +                if (SDEV_IS_PERSIST(dv->sdev_dotdot) &&
      604 +                    (SDEV_IS_PERSIST(dv) || !SDEV_IS_DYNAMIC(dv)))
      605 +                        dv->sdev_flags |= SDEV_PERSIST;
      606 +
      607 +                if (vtp->vt_vops) {
      608 +                        if (vtp->vt_global_vops)
      609 +                                *(vtp->vt_global_vops) = vtp->vt_vops;
      610 +
      611 +                        return (vtp->vt_vops);
      612 +                }
      613 +
      614 +                if (vtp->vt_service) {
      615 +                        fs_operation_def_t *templ;
      616 +                        templ = sdev_merge_vtab(vtp->vt_service);
      617 +                        if (vn_make_ops(vtp->vt_name,
      618 +                            (const fs_operation_def_t *)templ,
      619 +                            &vtp->vt_vops) != 0) {
      620 +                                cmn_err(CE_PANIC, "%s: malformed vnode ops\n",
      621 +                                    vtp->vt_name);
      622 +                                /*NOTREACHED*/
      623 +                        }
      624 +                        if (vtp->vt_global_vops) {
      625 +                                *(vtp->vt_global_vops) = vtp->vt_vops;
      626 +                        }
      627 +                        sdev_free_vtab(templ);
      628 +
      629 +                        return (vtp->vt_vops);
      630 +                }
      631 +
      632 +                return (sdev_vnodeops);
      633 +        }
      634 +
      635 +        /* child inherits the persistence of the parent */
      636 +        if (SDEV_IS_PERSIST(dv->sdev_dotdot))
      637 +                dv->sdev_flags |= SDEV_PERSIST;
      638 +
      639 +        return (sdev_vnodeops);
      640 +}
      641 +
      642 +static void
      643 +sdev_set_no_negcache(struct sdev_node *dv)
      644 +{
      645 +        int i;
      646 +        char *path;
      647 +
      648 +        ASSERT(dv->sdev_path);
      649 +        path = dv->sdev_path + strlen("/dev/");
      650 +
      651 +        for (i = 0; vtab[i].vt_name; i++) {
      652 +                if (strcmp(vtab[i].vt_name, path) == 0) {
      653 +                        if (vtab[i].vt_flags & SDEV_NO_NCACHE)
      654 +                                dv->sdev_flags |= SDEV_NO_NCACHE;
      655 +                        break;
      656 +                }
      657 +        }
      658 +}
      659 +
      660 +void *
      661 +sdev_get_vtor(struct sdev_node *dv)
      662 +{
      663 +        struct sdev_vop_table *vtp;
      664 +
      665 +        vtp = sdev_match(dv);
      666 +        if (vtp)
      667 +                return ((void *)vtp->vt_vtor);
      668 +        else
      669 +                return (NULL);
      670 +}
      671 +
      672 +/*
 536  673   * Build the base root inode
 537  674   */
 538  675  ino_t
 539  676  sdev_mkino(struct sdev_node *dv)
 540  677  {
 541  678          ino_t   ino;
 542  679  
 543  680          /*
 544  681           * for now, follow the lead of tmpfs here
 545  682           * need to someday understand the requirements here
↓ open down ↓ 257 lines elided ↑ open up ↑
 803  940          if (dv->sdev_symlink != NULL) {
 804  941                  kmem_free(dv->sdev_symlink, strlen(dv->sdev_symlink) + 1);
 805  942                  dv->sdev_symlink = NULL;
 806  943          }
 807  944  
 808  945          if (dv->sdev_path) {
 809  946                  kmem_free(dv->sdev_path, strlen(dv->sdev_path) + 1);
 810  947                  dv->sdev_path = NULL;
 811  948          }
 812  949  
 813      -        if (!SDEV_IS_GLOBAL(dv)) {
      950 +        if (!SDEV_IS_GLOBAL(dv))
 814  951                  sdev_prof_free(dv);
 815      -                if (dv->sdev_vnode->v_type != VLNK && dv->sdev_origin != NULL)
 816      -                        SDEV_RELE(dv->sdev_origin);
 817      -        }
 818  952  
 819  953          if (SDEVTOV(dv)->v_type == VDIR) {
 820  954                  ASSERT(SDEV_FIRST_ENTRY(dv) == NULL);
 821  955                  avl_destroy(&dv->sdev_entries);
 822  956          }
 823  957  
 824  958          mutex_destroy(&dv->sdev_lookup_lock);
 825  959          cv_destroy(&dv->sdev_lookup_cv);
 826  960  
 827  961          /* return node to initial state as per constructor */
↓ open down ↓ 1976 lines elided ↑ open up ↑
2804 2938          error = sdev_modctl_lookup(path, &vp);
2805 2939          sdcmn_err11(("modctl dev exists: %s by %s: %s\n",
2806 2940              path, curproc->p_user.u_comm,
2807 2941              (error == 0) ? "ok" : "failed"));
2808 2942          if (error == 0)
2809 2943                  VN_RELE(vp);
2810 2944  
2811 2945          return (error);
2812 2946  }
2813 2947  
     2948 +extern int sdev_vnodeops_tbl_size;
     2949 +
     2950 +/*
     2951 + * construct a new template with overrides from vtab
     2952 + */
     2953 +static fs_operation_def_t *
     2954 +sdev_merge_vtab(const fs_operation_def_t tab[])
     2955 +{
     2956 +        fs_operation_def_t *new;
     2957 +        const fs_operation_def_t *tab_entry;
     2958 +
     2959 +        /* make a copy of standard vnode ops table */
     2960 +        new = kmem_alloc(sdev_vnodeops_tbl_size, KM_SLEEP);
     2961 +        bcopy((void *)sdev_vnodeops_tbl, new, sdev_vnodeops_tbl_size);
     2962 +
     2963 +        /* replace the overrides from tab */
     2964 +        for (tab_entry = tab; tab_entry->name != NULL; tab_entry++) {
     2965 +                fs_operation_def_t *std_entry = new;
     2966 +                while (std_entry->name) {
     2967 +                        if (strcmp(tab_entry->name, std_entry->name) == 0) {
     2968 +                                std_entry->func = tab_entry->func;
     2969 +                                break;
     2970 +                        }
     2971 +                        std_entry++;
     2972 +                }
     2973 +                if (std_entry->name == NULL)
     2974 +                        cmn_err(CE_NOTE, "sdev_merge_vtab: entry %s unused.",
     2975 +                            tab_entry->name);
     2976 +        }
     2977 +
     2978 +        return (new);
     2979 +}
     2980 +
     2981 +/* free memory allocated by sdev_merge_vtab */
     2982 +static void
     2983 +sdev_free_vtab(fs_operation_def_t *new)
     2984 +{
     2985 +        kmem_free(new, sdev_vnodeops_tbl_size);
     2986 +}
     2987 +
2814 2988  /*
2815 2989   * a generic setattr() function
2816 2990   *
2817 2991   * note: flags only supports AT_UID and AT_GID.
2818 2992   *       Future enhancements can be done for other types, e.g. AT_MODE
2819 2993   */
2820 2994  int
2821 2995  devname_setattr_func(struct vnode *vp, struct vattr *vap, int flags,
2822 2996      struct cred *cred, int (*callback)(struct sdev_node *, struct vattr *,
2823 2997      int), int protocol)
↓ open down ↓ 148 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX