Print this page
6265 speed up mount/umount
*** 83,92 ****
--- 83,93 ----
#include <sys/attr.h>
#include <sys/zio.h>
#include <sys/spa.h>
#include <sys/lofi.h>
#include <sys/bootprops.h>
+ #include <sys/avl.h>
#include <vm/page.h>
#include <fs/fs_subr.h>
/* Private interfaces to create vopstats-related data structures */
*** 135,144 ****
--- 136,150 ----
static struct vfs root;
static struct vfs devices;
static struct vfs dev;
struct vfs *rootvfs = &root; /* pointer to root vfs; head of VFS list. */
+ avl_tree_t vfs_by_dev; /* avl tree to index mounted VFSs by dev */
+ avl_tree_t vfs_by_mntpnt; /* avl tree to index mounted VFSs by mntpnt */
+ uint64_t vfs_curr_mntix; /* counter to provide a unique mntix for
+ * entries in the above avl trees.
+ * protected by vfslist lock */
rvfs_t *rvfs_list; /* array of vfs ptrs for vfs hash list */
int vfshsz = 512; /* # of heads/locks in vfs hash arrays */
/* must be power of 2! */
timespec_t vfs_mnttab_ctime; /* mnttab created time */
timespec_t vfs_mnttab_mtime; /* mnttab last modified time */
*** 606,615 ****
--- 612,663 ----
{
vfs_sync(0);
}
/*
+ * compare function for vfs_by_dev avl tree. compare dev first, then mntix
+ */
+ static int
+ vfs_cmp_dev(const void *aa, const void *bb)
+ {
+ const vfs_t *a = aa;
+ const vfs_t *b = bb;
+
+ if (a->vfs_dev < b->vfs_dev)
+ return (-1);
+ if (a->vfs_dev > b->vfs_dev)
+ return (1);
+ if (a->vfs_mntix < b->vfs_mntix)
+ return (-1);
+ if (a->vfs_mntix > b->vfs_mntix)
+ return (1);
+ return (0);
+ }
+
+ /*
+ * compare function for vfs_by_mntpnt avl tree. compare mntpnt first, then mntix
+ */
+ static int
+ vfs_cmp_mntpnt(const void *aa, const void *bb)
+ {
+ const vfs_t *a = aa;
+ const vfs_t *b = bb;
+ int ret;
+
+ ret = strcmp(refstr_value(a->vfs_mntpt), refstr_value(b->vfs_mntpt));
+ if (ret < 0)
+ return (-1);
+ if (ret > 0)
+ return (1);
+ if (a->vfs_mntix < b->vfs_mntix)
+ return (-1);
+ if (a->vfs_mntix > b->vfs_mntix)
+ return (1);
+ return (0);
+ }
+
+ /*
* External routines.
*/
krwlock_t vfssw_lock; /* lock accesses to vfssw */
*** 816,825 ****
--- 864,881 ----
rw_init(&vfssw_lock, NULL, RW_DEFAULT, NULL);
rw_init(&vfslist, NULL, RW_DEFAULT, NULL);
/*
+ * Alloc the avl trees for quick indexing via dev and mountpoint
+ */
+ avl_create(&vfs_by_dev, vfs_cmp_dev, sizeof(vfs_t),
+ offsetof(vfs_t, vfs_avldev));
+ avl_create(&vfs_by_mntpnt, vfs_cmp_mntpnt, sizeof(vfs_t),
+ offsetof(vfs_t, vfs_avlmntpnt));
+
+ /*
* Alloc the vfs hash bucket array and locks
*/
rvfs_list = kmem_zalloc(vfshsz * sizeof (rvfs_t), KM_SLEEP);
/*
*** 3609,3618 ****
--- 3665,3686 ----
* the UFS.
*/
vfs_hash_add(vfsp, 0);
/*
+ * Link into tree indexed by mntpoint, for vfs_mntpoint2vfsp
+ * mntix discerns entries with the same key
+ */
+ vfsp->vfs_mntix = ++vfs_curr_mntix;
+ avl_add(&vfs_by_dev, vfsp);
+
+ /*
+ * Link into tree indexed by dev, for vfs_devismounted
+ */
+ avl_add(&vfs_by_mntpnt, vfsp);
+
+ /*
* update the mnttab modification time
*/
vfs_mnttab_modtimeupd();
vfs_list_unlock();
zone_rele(zone);
*** 3632,3641 ****
--- 3700,3715 ----
ASSERT(vfsp != rootvfs);
vfs_list_lock();
/*
+ * Remove from avl trees
+ */
+ avl_remove(&vfs_by_mntpnt, vfsp);
+ avl_remove(&vfs_by_dev, vfsp);
+
+ /*
* Remove from hash.
*/
vfs_hash_remove(vfsp);
/*
*** 3725,3746 ****
int
vfs_devismounted(dev_t dev)
{
struct vfs *vfsp;
! int found;
vfs_list_read_lock();
! vfsp = rootvfs;
! found = 0;
! do {
! if (vfsp->vfs_dev == dev) {
found = 1;
- break;
- }
- vfsp = vfsp->vfs_next;
- } while (vfsp != rootvfs);
vfs_list_unlock();
return (found);
}
--- 3799,3828 ----
int
vfs_devismounted(dev_t dev)
{
struct vfs *vfsp;
! int found = 0;
! struct vfs search;
! avl_index_t index;
!
! search.vfs_dev = dev;
! search.vfs_mntix = 0;
vfs_list_read_lock();
!
! /*
! * there might be several entries with the same dev in the tree,
! * only discerned by mntix. To find the first, we start with a mntix
! * of 0. The search will fail. The following avl_nearest will give
! * us the actual first entry.
! */
! VERIFY(avl_find(&vfs_by_dev, &search, &index) == NULL);
! vfsp = avl_nearest(&vfs_by_dev, index, AVL_AFTER);
!
! if (vfsp != NULL && vfsp->vfs_dev == dev)
found = 1;
vfs_list_unlock();
return (found);
}
*** 3752,3784 ****
struct vfs *
vfs_dev2vfsp(dev_t dev)
{
struct vfs *vfsp;
int found;
vfs_list_read_lock();
! vfsp = rootvfs;
found = 0;
! do {
/*
* The following could be made more efficient by making
* the entire loop use vfs_zone_next if the call is from
* a zone. The only callers, however, ustat(2) and
* umount2(2), don't seem to justify the added
* complexity at present.
*/
! if (vfsp->vfs_dev == dev &&
! ZONE_PATH_VISIBLE(refstr_value(vfsp->vfs_mntpt),
curproc->p_zone)) {
VFS_HOLD(vfsp);
found = 1;
break;
}
! vfsp = vfsp->vfs_next;
! } while (vfsp != rootvfs);
vfs_list_unlock();
! return (found ? vfsp: NULL);
}
/*
* Search the vfs list for a specified mntpoint. Returns a pointer to it
* or NULL if no suitable entry is found. The caller of this routine
--- 3834,3879 ----
struct vfs *
vfs_dev2vfsp(dev_t dev)
{
struct vfs *vfsp;
int found;
+ struct vfs search;
+ avl_index_t index;
+
+ search.vfs_dev = dev;
+ search.vfs_mntix = 0;
vfs_list_read_lock();
!
! /*
! * there might be several entries with the same dev in the tree,
! * only discerned by mntix. To find the first, we start with a mntix
! * of 0. The search will fail. The following avl_nearest will give
! * us the actual first entry.
! */
! VERIFY(avl_find(&vfs_by_dev, &search, &index) == NULL);
! vfsp = avl_nearest(&vfs_by_dev, index, AVL_AFTER);
!
found = 0;
! while (vfsp != NULL && vfsp->vfs_dev == dev) {
/*
* The following could be made more efficient by making
* the entire loop use vfs_zone_next if the call is from
* a zone. The only callers, however, ustat(2) and
* umount2(2), don't seem to justify the added
* complexity at present.
*/
! if (ZONE_PATH_VISIBLE(refstr_value(vfsp->vfs_mntpt),
curproc->p_zone)) {
VFS_HOLD(vfsp);
found = 1;
break;
}
! vfsp = AVL_NEXT(&vfs_by_dev, vfsp);
! }
vfs_list_unlock();
! return (found ? vfsp : NULL);
}
/*
* Search the vfs list for a specified mntpoint. Returns a pointer to it
* or NULL if no suitable entry is found. The caller of this routine
*** 3801,3818 ****
vfs_list_read_lock();
if (getzoneid() == GLOBAL_ZONEID) {
/*
* The global zone may see filesystems in any zone.
*/
! vfsp = rootvfs->vfs_prev;
! do {
! if (strcmp(refstr_value(vfsp->vfs_mntpt), mp) == 0) {
retvfsp = vfsp;
- break;
- }
- vfsp = vfsp->vfs_prev;
- } while (vfsp != rootvfs->vfs_prev);
} else if ((list = zone->zone_vfslist) != NULL) {
const char *mntpt;
vfsp = list->vfs_zone_prev;
do {
--- 3896,3925 ----
vfs_list_read_lock();
if (getzoneid() == GLOBAL_ZONEID) {
/*
* The global zone may see filesystems in any zone.
*/
! struct vfs search;
! search.vfs_mntpt = refstr_alloc(mp);
! search.vfs_mntix = UINT64_MAX;
! avl_index_t index;
!
! /*
! * there might be several entries with the same mntpnt in the
! * tree, only discerned by mntix. To find the last, we start
! * with a mntix of UINT64_MAX. The search will fail. The
! * following avl_nearest will give us the actual last entry
! * matching the mntpnt.
! */
! VERIFY(avl_find(&vfs_by_mntpnt, &search, &index) == 0);
! vfsp = avl_nearest(&vfs_by_mntpnt, index, AVL_BEFORE);
!
! refstr_rele(search.vfs_mntpt);
!
! if (vfsp != NULL &&
! strcmp(refstr_value(vfsp->vfs_mntpt), mp) == 0)
retvfsp = vfsp;
} else if ((list = zone->zone_vfslist) != NULL) {
const char *mntpt;
vfsp = list->vfs_zone_prev;
do {