Print this page
6265 speed up mount/umount


  68 #include <sys/modctl.h>
  69 #include <sys/ddi.h>
  70 #include <sys/pathname.h>
  71 #include <sys/bootconf.h>
  72 #include <sys/dumphdr.h>
  73 #include <sys/dc_ki.h>
  74 #include <sys/poll.h>
  75 #include <sys/sunddi.h>
  76 #include <sys/sysmacros.h>
  77 #include <sys/zone.h>
  78 #include <sys/policy.h>
  79 #include <sys/ctfs.h>
  80 #include <sys/objfs.h>
  81 #include <sys/console.h>
  82 #include <sys/reboot.h>
  83 #include <sys/attr.h>
  84 #include <sys/zio.h>
  85 #include <sys/spa.h>
  86 #include <sys/lofi.h>
  87 #include <sys/bootprops.h>

  88 
  89 #include <vm/page.h>
  90 
  91 #include <fs/fs_subr.h>
  92 /* Private interfaces to create vopstats-related data structures */
  93 extern void             initialize_vopstats(vopstats_t *);
  94 extern vopstats_t       *get_fstype_vopstats(struct vfs *, struct vfssw *);
  95 extern vsk_anchor_t     *get_vskstat_anchor(struct vfs *);
  96 
  97 static void vfs_clearmntopt_nolock(mntopts_t *, const char *, int);
  98 static void vfs_setmntopt_nolock(mntopts_t *, const char *,
  99     const char *, int, int);
 100 static int  vfs_optionisset_nolock(const mntopts_t *, const char *, char **);
 101 static void vfs_freemnttab(struct vfs *);
 102 static void vfs_freeopt(mntopt_t *);
 103 static void vfs_swapopttbl_nolock(mntopts_t *, mntopts_t *);
 104 static void vfs_swapopttbl(mntopts_t *, mntopts_t *);
 105 static void vfs_copyopttbl_extend(const mntopts_t *, mntopts_t *, int);
 106 static void vfs_createopttbl_extend(mntopts_t *, const char *,
 107     const mntopts_t *);


 120 static kmutex_t         vfs_miplist_mutex;
 121 static struct ipmnt     *vfs_miplist = NULL;
 122 static struct ipmnt     *vfs_miplist_end = NULL;
 123 
 124 static kmem_cache_t *vfs_cache; /* Pointer to VFS kmem cache */
 125 
 126 /*
 127  * VFS global data.
 128  */
 129 vnode_t *rootdir;               /* pointer to root inode vnode. */
 130 vnode_t *devicesdir;            /* pointer to inode of devices root */
 131 vnode_t *devdir;                /* pointer to inode of dev root */
 132 
 133 char *server_rootpath;          /* root path for diskless clients */
 134 char *server_hostname;          /* hostname of diskless server */
 135 
 136 static struct vfs root;
 137 static struct vfs devices;
 138 static struct vfs dev;
 139 struct vfs *rootvfs = &root;        /* pointer to root vfs; head of VFS list. */





 140 rvfs_t *rvfs_list;              /* array of vfs ptrs for vfs hash list */
 141 int vfshsz = 512;               /* # of heads/locks in vfs hash arrays */
 142                                 /* must be power of 2!  */
 143 timespec_t vfs_mnttab_ctime;    /* mnttab created time */
 144 timespec_t vfs_mnttab_mtime;    /* mnttab last modified time */
 145 char *vfs_dummyfstype = "\0";
 146 struct pollhead vfs_pollhd;     /* for mnttab pollers */
 147 struct vnode *vfs_mntdummyvp;   /* to fake mnttab read/write for file events */
 148 int     mntfstype;              /* will be set once mnt fs is mounted */
 149 
 150 /*
 151  * Table for generic options recognized in the VFS layer and acted
 152  * on at this level before parsing file system specific options.
 153  * The nosuid option is stronger than any of the devices and setuid
 154  * options, so those are canceled when nosuid is seen.
 155  *
 156  * All options which are added here need to be added to the
 157  * list of standard options in usr/src/cmd/fs.d/fslib.c as well.
 158  */
 159 /*


 591         for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) {
 592                 if (ALLOCATED_VFSSW(vswp) && VFS_INSTALLED(vswp)) {
 593                         vfs_refvfssw(vswp);
 594                         RUNLOCK_VFSSW();
 595                         (void) (*vswp->vsw_vfsops.vfs_sync)(NULL, flag,
 596                             CRED());
 597                         vfs_unrefvfssw(vswp);
 598                         RLOCK_VFSSW();
 599                 }
 600         }
 601         RUNLOCK_VFSSW();
 602 }
 603 
 604 void
 605 sync(void)
 606 {
 607         vfs_sync(0);
 608 }
 609 
 610 /*










































 611  * External routines.
 612  */
 613 
 614 krwlock_t vfssw_lock;   /* lock accesses to vfssw */
 615 
 616 /*
 617  * Lock for accessing the vfs linked list.  Initialized in vfs_mountroot(),
 618  * but otherwise should be accessed only via vfs_list_lock() and
 619  * vfs_list_unlock().  Also used to protect the timestamp for mods to the list.
 620  */
 621 static krwlock_t vfslist;
 622 
 623 /*
 624  * Mount devfs on /devices. This is done right after root is mounted
 625  * to provide device access support for the system
 626  */
 627 static void
 628 vfs_mountdevices(void)
 629 {
 630         struct vfssw *vsw;


 801                 VFS_RELE(vfsp);
 802         VN_RELE(mvp);
 803 }
 804 
 805 /*
 806  * vfs_mountroot is called by main() to mount the root filesystem.
 807  */
 808 void
 809 vfs_mountroot(void)
 810 {
 811         struct vnode    *rvp = NULL;
 812         char            *path;
 813         size_t          plen;
 814         struct vfssw    *vswp;
 815         proc_t          *p;
 816 
 817         rw_init(&vfssw_lock, NULL, RW_DEFAULT, NULL);
 818         rw_init(&vfslist, NULL, RW_DEFAULT, NULL);
 819 
 820         /*








 821          * Alloc the vfs hash bucket array and locks
 822          */
 823         rvfs_list = kmem_zalloc(vfshsz * sizeof (rvfs_t), KM_SLEEP);
 824 
 825         /*
 826          * Call machine-dependent routine "rootconf" to choose a root
 827          * file system type.
 828          */
 829         if (rootconf())
 830                 panic("vfs_mountroot: cannot mount root");
 831         /*
 832          * Get vnode for '/'.  Set up rootdir, u.u_rdir and u.u_cdir
 833          * to point to it.  These are used by lookuppn() so that it
 834          * knows where to start from ('/' or '.').
 835          */
 836         vfs_setmntpoint(rootvfs, "/", 0);
 837         if (VFS_ROOT(rootvfs, &rootdir))
 838                 panic("vfs_mountroot: no root vnode");
 839 
 840         /*


3594                  */
3595                 if (zone->zone_vfslist == NULL) {
3596                         ASSERT(zone != global_zone);
3597                         zone->zone_vfslist = vfsp;
3598                 } else {
3599                         zone->zone_vfslist->vfs_zone_prev->vfs_zone_next = vfsp;
3600                         vfsp->vfs_zone_prev = zone->zone_vfslist->vfs_zone_prev;
3601                         zone->zone_vfslist->vfs_zone_prev = vfsp;
3602                         vfsp->vfs_zone_next = zone->zone_vfslist;
3603                 }
3604         }
3605 
3606         /*
3607          * Link into the hash table, inserting it at the end, so that LOFS
3608          * with the same fsid as UFS (or other) file systems will not hide
3609          * the UFS.
3610          */
3611         vfs_hash_add(vfsp, 0);
3612 
3613         /*












3614          * update the mnttab modification time
3615          */
3616         vfs_mnttab_modtimeupd();
3617         vfs_list_unlock();
3618         zone_rele(zone);
3619 }
3620 
3621 void
3622 vfs_list_remove(struct vfs *vfsp)
3623 {
3624         zone_t *zone;
3625 
3626         zone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt));
3627         ASSERT(zone != NULL);
3628         /*
3629          * Callers are responsible for preventing attempts to unmount the
3630          * root.
3631          */
3632         ASSERT(vfsp != rootvfs);
3633 
3634         vfs_list_lock();
3635 
3636         /*






3637          * Remove from hash.
3638          */
3639         vfs_hash_remove(vfsp);
3640 
3641         /*
3642          * Remove from vfs list.
3643          */
3644         vfsp->vfs_prev->vfs_next = vfsp->vfs_next;
3645         vfsp->vfs_next->vfs_prev = vfsp->vfs_prev;
3646         vfsp->vfs_next = vfsp->vfs_prev = NULL;
3647 
3648         /*
3649          * Remove from zone-specific vfs list.
3650          */
3651         if (zone->zone_vfslist == vfsp)
3652                 zone->zone_vfslist = vfsp->vfs_zone_next;
3653 
3654         if (vfsp->vfs_zone_next == vfsp) {
3655                 ASSERT(vfsp->vfs_zone_prev == vfsp);
3656                 ASSERT(zone->zone_vfslist == vfsp);


3710         for (mipp = vfs_miplist; mipp != NULL; mipp = mipp->mip_next) {
3711                 if (mipp->mip_dev == dev) {
3712                         if (mipp->mip_vfsp != vfsp)
3713                                 retval = 1;
3714                         break;
3715                 }
3716         }
3717         mutex_exit(&vfs_miplist_mutex);
3718         return (retval);
3719 }
3720 
3721 /*
3722  * Search the vfs list for a specified device.  Returns 1, if entry is found
3723  * or 0 if no suitable entry is found.
3724  */
3725 
3726 int
3727 vfs_devismounted(dev_t dev)
3728 {
3729         struct vfs *vfsp;
3730         int found;





3731 
3732         vfs_list_read_lock();
3733         vfsp = rootvfs;
3734         found = 0;
3735         do {
3736                 if (vfsp->vfs_dev == dev) {







3737                         found = 1;
3738                         break;
3739                 }
3740                 vfsp = vfsp->vfs_next;
3741         } while (vfsp != rootvfs);
3742 
3743         vfs_list_unlock();
3744         return (found);
3745 }
3746 
3747 /*
3748  * Search the vfs list for a specified device.  Returns a pointer to it
3749  * or NULL if no suitable entry is found. The caller of this routine
3750  * is responsible for releasing the returned vfs pointer.
3751  */
3752 struct vfs *
3753 vfs_dev2vfsp(dev_t dev)
3754 {
3755         struct vfs *vfsp;
3756         int found;





3757 
3758         vfs_list_read_lock();
3759         vfsp = rootvfs;









3760         found = 0;
3761         do {
3762                 /*
3763                  * The following could be made more efficient by making
3764                  * the entire loop use vfs_zone_next if the call is from
3765                  * a zone.  The only callers, however, ustat(2) and
3766                  * umount2(2), don't seem to justify the added
3767                  * complexity at present.
3768                  */
3769                 if (vfsp->vfs_dev == dev &&
3770                     ZONE_PATH_VISIBLE(refstr_value(vfsp->vfs_mntpt),
3771                     curproc->p_zone)) {
3772                         VFS_HOLD(vfsp);
3773                         found = 1;
3774                         break;
3775                 }
3776                 vfsp = vfsp->vfs_next;
3777         } while (vfsp != rootvfs);
3778         vfs_list_unlock();
3779         return (found ? vfsp: NULL);
3780 }
3781 
3782 /*
3783  * Search the vfs list for a specified mntpoint.  Returns a pointer to it
3784  * or NULL if no suitable entry is found. The caller of this routine
3785  * is responsible for releasing the returned vfs pointer.
3786  *
3787  * Note that if multiple mntpoints match, the last one matching is
3788  * returned in an attempt to return the "top" mount when overlay
3789  * mounts are covering the same mount point.  This is accomplished by starting
3790  * at the end of the list and working our way backwards, stopping at the first
3791  * matching mount.
3792  */
3793 struct vfs *
3794 vfs_mntpoint2vfsp(const char *mp)
3795 {
3796         struct vfs *vfsp;
3797         struct vfs *retvfsp = NULL;
3798         zone_t *zone = curproc->p_zone;
3799         struct vfs *list;
3800 
3801         vfs_list_read_lock();
3802         if (getzoneid() == GLOBAL_ZONEID) {
3803                 /*
3804                  * The global zone may see filesystems in any zone.
3805                  */
3806                 vfsp = rootvfs->vfs_prev;
3807                 do {
3808                         if (strcmp(refstr_value(vfsp->vfs_mntpt), mp) == 0) {
















3809                                 retvfsp = vfsp;
3810                                 break;
3811                         }
3812                         vfsp = vfsp->vfs_prev;
3813                 } while (vfsp != rootvfs->vfs_prev);
3814         } else if ((list = zone->zone_vfslist) != NULL) {
3815                 const char *mntpt;
3816 
3817                 vfsp = list->vfs_zone_prev;
3818                 do {
3819                         mntpt = refstr_value(vfsp->vfs_mntpt);
3820                         mntpt = ZONE_PATH_TRANSLATE(mntpt, zone);
3821                         if (strcmp(mntpt, mp) == 0) {
3822                                 retvfsp = vfsp;
3823                                 break;
3824                         }
3825                         vfsp = vfsp->vfs_zone_prev;
3826                 } while (vfsp != list->vfs_zone_prev);
3827         }
3828         if (retvfsp)
3829                 VFS_HOLD(retvfsp);
3830         vfs_list_unlock();
3831         return (retvfsp);
3832 }
3833 




  68 #include <sys/modctl.h>
  69 #include <sys/ddi.h>
  70 #include <sys/pathname.h>
  71 #include <sys/bootconf.h>
  72 #include <sys/dumphdr.h>
  73 #include <sys/dc_ki.h>
  74 #include <sys/poll.h>
  75 #include <sys/sunddi.h>
  76 #include <sys/sysmacros.h>
  77 #include <sys/zone.h>
  78 #include <sys/policy.h>
  79 #include <sys/ctfs.h>
  80 #include <sys/objfs.h>
  81 #include <sys/console.h>
  82 #include <sys/reboot.h>
  83 #include <sys/attr.h>
  84 #include <sys/zio.h>
  85 #include <sys/spa.h>
  86 #include <sys/lofi.h>
  87 #include <sys/bootprops.h>
  88 #include <sys/avl.h>
  89 
  90 #include <vm/page.h>
  91 
  92 #include <fs/fs_subr.h>
  93 /* Private interfaces to create vopstats-related data structures */
  94 extern void             initialize_vopstats(vopstats_t *);
  95 extern vopstats_t       *get_fstype_vopstats(struct vfs *, struct vfssw *);
  96 extern vsk_anchor_t     *get_vskstat_anchor(struct vfs *);
  97 
  98 static void vfs_clearmntopt_nolock(mntopts_t *, const char *, int);
  99 static void vfs_setmntopt_nolock(mntopts_t *, const char *,
 100     const char *, int, int);
 101 static int  vfs_optionisset_nolock(const mntopts_t *, const char *, char **);
 102 static void vfs_freemnttab(struct vfs *);
 103 static void vfs_freeopt(mntopt_t *);
 104 static void vfs_swapopttbl_nolock(mntopts_t *, mntopts_t *);
 105 static void vfs_swapopttbl(mntopts_t *, mntopts_t *);
 106 static void vfs_copyopttbl_extend(const mntopts_t *, mntopts_t *, int);
 107 static void vfs_createopttbl_extend(mntopts_t *, const char *,
 108     const mntopts_t *);


 121 static kmutex_t         vfs_miplist_mutex;
 122 static struct ipmnt     *vfs_miplist = NULL;
 123 static struct ipmnt     *vfs_miplist_end = NULL;
 124 
 125 static kmem_cache_t *vfs_cache; /* Pointer to VFS kmem cache */
 126 
 127 /*
 128  * VFS global data.
 129  */
 130 vnode_t *rootdir;               /* pointer to root inode vnode. */
 131 vnode_t *devicesdir;            /* pointer to inode of devices root */
 132 vnode_t *devdir;                /* pointer to inode of dev root */
 133 
 134 char *server_rootpath;          /* root path for diskless clients */
 135 char *server_hostname;          /* hostname of diskless server */
 136 
 137 static struct vfs root;
 138 static struct vfs devices;
 139 static struct vfs dev;
 140 struct vfs *rootvfs = &root;        /* pointer to root vfs; head of VFS list. */
 141 avl_tree_t vfs_by_dev;          /* avl tree to index mounted VFSs by dev */
 142 avl_tree_t vfs_by_mntpnt;       /* avl tree to index mounted VFSs by mntpnt */
 143 uint64_t vfs_curr_mntix;        /* counter to provide a unique mntix for
 144                                  * entries in the above avl trees.
 145                                  * protected by vfslist lock */
 146 rvfs_t *rvfs_list;              /* array of vfs ptrs for vfs hash list */
 147 int vfshsz = 512;               /* # of heads/locks in vfs hash arrays */
 148                                 /* must be power of 2!  */
 149 timespec_t vfs_mnttab_ctime;    /* mnttab created time */
 150 timespec_t vfs_mnttab_mtime;    /* mnttab last modified time */
 151 char *vfs_dummyfstype = "\0";
 152 struct pollhead vfs_pollhd;     /* for mnttab pollers */
 153 struct vnode *vfs_mntdummyvp;   /* to fake mnttab read/write for file events */
 154 int     mntfstype;              /* will be set once mnt fs is mounted */
 155 
 156 /*
 157  * Table for generic options recognized in the VFS layer and acted
 158  * on at this level before parsing file system specific options.
 159  * The nosuid option is stronger than any of the devices and setuid
 160  * options, so those are canceled when nosuid is seen.
 161  *
 162  * All options which are added here need to be added to the
 163  * list of standard options in usr/src/cmd/fs.d/fslib.c as well.
 164  */
 165 /*


 597         for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) {
 598                 if (ALLOCATED_VFSSW(vswp) && VFS_INSTALLED(vswp)) {
 599                         vfs_refvfssw(vswp);
 600                         RUNLOCK_VFSSW();
 601                         (void) (*vswp->vsw_vfsops.vfs_sync)(NULL, flag,
 602                             CRED());
 603                         vfs_unrefvfssw(vswp);
 604                         RLOCK_VFSSW();
 605                 }
 606         }
 607         RUNLOCK_VFSSW();
 608 }
 609 
 610 void
 611 sync(void)
 612 {
 613         vfs_sync(0);
 614 }
 615 
 616 /*
 617  * compare function for vfs_by_dev avl tree. compare dev first, then mntix
 618  */
 619 static int
 620 vfs_cmp_dev(const void *aa, const void *bb)
 621 {
 622         const vfs_t *a = aa;
 623         const vfs_t *b = bb;
 624 
 625         if (a->vfs_dev < b->vfs_dev)
 626                 return (-1);
 627         if (a->vfs_dev > b->vfs_dev)
 628                 return (1);
 629         if (a->vfs_mntix < b->vfs_mntix)
 630                 return (-1);
 631         if (a->vfs_mntix > b->vfs_mntix)
 632                 return (1);
 633         return (0);
 634 }
 635 
 636 /*
 637  * compare function for vfs_by_mntpnt avl tree. compare mntpnt first, then mntix
 638  */
 639 static int
 640 vfs_cmp_mntpnt(const void *aa, const void *bb)
 641 {
 642         const vfs_t *a = aa;
 643         const vfs_t *b = bb;
 644         int ret;
 645 
 646         ret = strcmp(refstr_value(a->vfs_mntpt), refstr_value(b->vfs_mntpt));
 647         if (ret < 0)
 648                 return (-1);
 649         if (ret > 0)
 650                 return (1);
 651         if (a->vfs_mntix < b->vfs_mntix)
 652                 return (-1);
 653         if (a->vfs_mntix > b->vfs_mntix)
 654                 return (1);
 655         return (0);
 656 }
 657 
 658 /*
 659  * External routines.
 660  */
 661 
 662 krwlock_t vfssw_lock;   /* lock accesses to vfssw */
 663 
 664 /*
 665  * Lock for accessing the vfs linked list.  Initialized in vfs_mountroot(),
 666  * but otherwise should be accessed only via vfs_list_lock() and
 667  * vfs_list_unlock().  Also used to protect the timestamp for mods to the list.
 668  */
 669 static krwlock_t vfslist;
 670 
 671 /*
 672  * Mount devfs on /devices. This is done right after root is mounted
 673  * to provide device access support for the system
 674  */
 675 static void
 676 vfs_mountdevices(void)
 677 {
 678         struct vfssw *vsw;


 849                 VFS_RELE(vfsp);
 850         VN_RELE(mvp);
 851 }
 852 
 853 /*
 854  * vfs_mountroot is called by main() to mount the root filesystem.
 855  */
 856 void
 857 vfs_mountroot(void)
 858 {
 859         struct vnode    *rvp = NULL;
 860         char            *path;
 861         size_t          plen;
 862         struct vfssw    *vswp;
 863         proc_t          *p;
 864 
 865         rw_init(&vfssw_lock, NULL, RW_DEFAULT, NULL);
 866         rw_init(&vfslist, NULL, RW_DEFAULT, NULL);
 867 
 868         /*
 869          * Alloc the avl trees for quick indexing via dev and mountpoint
 870          */
 871         avl_create(&vfs_by_dev, vfs_cmp_dev, sizeof(vfs_t),
 872             offsetof(vfs_t, vfs_avldev));
 873         avl_create(&vfs_by_mntpnt, vfs_cmp_mntpnt, sizeof(vfs_t),
 874             offsetof(vfs_t, vfs_avlmntpnt));
 875 
 876         /*
 877          * Alloc the vfs hash bucket array and locks
 878          */
 879         rvfs_list = kmem_zalloc(vfshsz * sizeof (rvfs_t), KM_SLEEP);
 880 
 881         /*
 882          * Call machine-dependent routine "rootconf" to choose a root
 883          * file system type.
 884          */
 885         if (rootconf())
 886                 panic("vfs_mountroot: cannot mount root");
 887         /*
 888          * Get vnode for '/'.  Set up rootdir, u.u_rdir and u.u_cdir
 889          * to point to it.  These are used by lookuppn() so that it
 890          * knows where to start from ('/' or '.').
 891          */
 892         vfs_setmntpoint(rootvfs, "/", 0);
 893         if (VFS_ROOT(rootvfs, &rootdir))
 894                 panic("vfs_mountroot: no root vnode");
 895 
 896         /*


3650                  */
3651                 if (zone->zone_vfslist == NULL) {
3652                         ASSERT(zone != global_zone);
3653                         zone->zone_vfslist = vfsp;
3654                 } else {
3655                         zone->zone_vfslist->vfs_zone_prev->vfs_zone_next = vfsp;
3656                         vfsp->vfs_zone_prev = zone->zone_vfslist->vfs_zone_prev;
3657                         zone->zone_vfslist->vfs_zone_prev = vfsp;
3658                         vfsp->vfs_zone_next = zone->zone_vfslist;
3659                 }
3660         }
3661 
3662         /*
3663          * Link into the hash table, inserting it at the end, so that LOFS
3664          * with the same fsid as UFS (or other) file systems will not hide
3665          * the UFS.
3666          */
3667         vfs_hash_add(vfsp, 0);
3668 
3669         /*
3670          * Link into tree indexed by mntpoint, for vfs_mntpoint2vfsp
3671          * mntix discerns entries with the same key
3672          */
3673         vfsp->vfs_mntix = ++vfs_curr_mntix;
3674         avl_add(&vfs_by_dev, vfsp);
3675 
3676         /*
3677          * Link into tree indexed by dev, for vfs_devismounted
3678          */
3679         avl_add(&vfs_by_mntpnt, vfsp);
3680 
3681         /*
3682          * update the mnttab modification time
3683          */
3684         vfs_mnttab_modtimeupd();
3685         vfs_list_unlock();
3686         zone_rele(zone);
3687 }
3688 
3689 void
3690 vfs_list_remove(struct vfs *vfsp)
3691 {
3692         zone_t *zone;
3693 
3694         zone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt));
3695         ASSERT(zone != NULL);
3696         /*
3697          * Callers are responsible for preventing attempts to unmount the
3698          * root.
3699          */
3700         ASSERT(vfsp != rootvfs);
3701 
3702         vfs_list_lock();
3703 
3704         /*
3705          * Remove from avl trees
3706          */
3707         avl_remove(&vfs_by_mntpnt, vfsp);
3708         avl_remove(&vfs_by_dev, vfsp);
3709 
3710         /*
3711          * Remove from hash.
3712          */
3713         vfs_hash_remove(vfsp);
3714 
3715         /*
3716          * Remove from vfs list.
3717          */
3718         vfsp->vfs_prev->vfs_next = vfsp->vfs_next;
3719         vfsp->vfs_next->vfs_prev = vfsp->vfs_prev;
3720         vfsp->vfs_next = vfsp->vfs_prev = NULL;
3721 
3722         /*
3723          * Remove from zone-specific vfs list.
3724          */
3725         if (zone->zone_vfslist == vfsp)
3726                 zone->zone_vfslist = vfsp->vfs_zone_next;
3727 
3728         if (vfsp->vfs_zone_next == vfsp) {
3729                 ASSERT(vfsp->vfs_zone_prev == vfsp);
3730                 ASSERT(zone->zone_vfslist == vfsp);


3784         for (mipp = vfs_miplist; mipp != NULL; mipp = mipp->mip_next) {
3785                 if (mipp->mip_dev == dev) {
3786                         if (mipp->mip_vfsp != vfsp)
3787                                 retval = 1;
3788                         break;
3789                 }
3790         }
3791         mutex_exit(&vfs_miplist_mutex);
3792         return (retval);
3793 }
3794 
3795 /*
3796  * Search the vfs list for a specified device.  Returns 1, if entry is found
3797  * or 0 if no suitable entry is found.
3798  */
3799 
3800 int
3801 vfs_devismounted(dev_t dev)
3802 {
3803         struct vfs *vfsp;
3804         int found = 0;
3805         struct vfs search;
3806         avl_index_t index;
3807 
3808         search.vfs_dev = dev;
3809         search.vfs_mntix = 0;
3810 
3811         vfs_list_read_lock();
3812 
3813         /*
3814          * there might be several entries with the same dev in the tree,
3815          * only discerned by mntix. To find the first, we start with a mntix
3816          * of 0. The search will fail. The following avl_nearest will give
3817          * us the actual first entry.
3818          */
3819         VERIFY(avl_find(&vfs_by_dev, &search, &index) == NULL);
3820         vfsp = avl_nearest(&vfs_by_dev, index, AVL_AFTER);
3821 
3822         if (vfsp != NULL && vfsp->vfs_dev == dev)
3823                 found = 1;




3824 
3825         vfs_list_unlock();
3826         return (found);
3827 }
3828 
3829 /*
3830  * Search the vfs list for a specified device.  Returns a pointer to it
3831  * or NULL if no suitable entry is found. The caller of this routine
3832  * is responsible for releasing the returned vfs pointer.
3833  */
3834 struct vfs *
3835 vfs_dev2vfsp(dev_t dev)
3836 {
3837         struct vfs *vfsp;
3838         int found;
3839         struct vfs search;
3840         avl_index_t index;
3841 
3842         search.vfs_dev = dev;
3843         search.vfs_mntix = 0;
3844 
3845         vfs_list_read_lock();
3846 
3847         /*
3848          * there might be several entries with the same dev in the tree,
3849          * only discerned by mntix. To find the first, we start with a mntix
3850          * of 0. The search will fail. The following avl_nearest will give
3851          * us the actual first entry.
3852          */
3853         VERIFY(avl_find(&vfs_by_dev, &search, &index) == NULL);
3854         vfsp = avl_nearest(&vfs_by_dev, index, AVL_AFTER);
3855 
3856         found = 0;
3857         while (vfsp != NULL && vfsp->vfs_dev == dev) {
3858                 /*
3859                  * The following could be made more efficient by making
3860                  * the entire loop use vfs_zone_next if the call is from
3861                  * a zone.  The only callers, however, ustat(2) and
3862                  * umount2(2), don't seem to justify the added
3863                  * complexity at present.
3864                  */
3865                 if (ZONE_PATH_VISIBLE(refstr_value(vfsp->vfs_mntpt),

3866                     curproc->p_zone)) {
3867                         VFS_HOLD(vfsp);
3868                         found = 1;
3869                         break;
3870                 }
3871                 vfsp = AVL_NEXT(&vfs_by_dev, vfsp);
3872         }
3873         vfs_list_unlock();
3874         return (found ? vfsp : NULL);
3875 }
3876 
3877 /*
3878  * Search the vfs list for a specified mntpoint.  Returns a pointer to it
3879  * or NULL if no suitable entry is found. The caller of this routine
3880  * is responsible for releasing the returned vfs pointer.
3881  *
3882  * Note that if multiple mntpoints match, the last one matching is
3883  * returned in an attempt to return the "top" mount when overlay
3884  * mounts are covering the same mount point.  This is accomplished by starting
3885  * at the end of the list and working our way backwards, stopping at the first
3886  * matching mount.
3887  */
3888 struct vfs *
3889 vfs_mntpoint2vfsp(const char *mp)
3890 {
3891         struct vfs *vfsp;
3892         struct vfs *retvfsp = NULL;
3893         zone_t *zone = curproc->p_zone;
3894         struct vfs *list;
3895 
3896         vfs_list_read_lock();
3897         if (getzoneid() == GLOBAL_ZONEID) {
3898                 /*
3899                  * The global zone may see filesystems in any zone.
3900                  */
3901                 struct vfs search;
3902                 search.vfs_mntpt = refstr_alloc(mp);
3903                 search.vfs_mntix = UINT64_MAX;
3904                 avl_index_t index;
3905 
3906                 /*
3907                  * there might be several entries with the same mntpnt in the
3908                  * tree, only discerned by mntix. To find the last, we start
3909                  * with a mntix of UINT64_MAX. The search will fail. The
3910                  * following avl_nearest will give  us the actual last entry
3911                  * matching the mntpnt.
3912                  */
3913                 VERIFY(avl_find(&vfs_by_mntpnt, &search, &index) == 0);
3914                 vfsp = avl_nearest(&vfs_by_mntpnt, index, AVL_BEFORE);
3915 
3916                 refstr_rele(search.vfs_mntpt);
3917 
3918                 if (vfsp != NULL &&
3919                     strcmp(refstr_value(vfsp->vfs_mntpt), mp) == 0)
3920                         retvfsp = vfsp;




3921         } else if ((list = zone->zone_vfslist) != NULL) {
3922                 const char *mntpt;
3923 
3924                 vfsp = list->vfs_zone_prev;
3925                 do {
3926                         mntpt = refstr_value(vfsp->vfs_mntpt);
3927                         mntpt = ZONE_PATH_TRANSLATE(mntpt, zone);
3928                         if (strcmp(mntpt, mp) == 0) {
3929                                 retvfsp = vfsp;
3930                                 break;
3931                         }
3932                         vfsp = vfsp->vfs_zone_prev;
3933                 } while (vfsp != list->vfs_zone_prev);
3934         }
3935         if (retvfsp)
3936                 VFS_HOLD(retvfsp);
3937         vfs_list_unlock();
3938         return (retvfsp);
3939 }
3940