summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/zfs/zfs_fuid.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/zfs/zfs_fuid.c')
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_fuid.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/usr/src/uts/common/fs/zfs/zfs_fuid.c b/usr/src/uts/common/fs/zfs/zfs_fuid.c
index fe773fdd33..fe1400ee06 100644
--- a/usr/src/uts/common/fs/zfs/zfs_fuid.c
+++ b/usr/src/uts/common/fs/zfs/zfs_fuid.c
@@ -23,8 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/zfs_context.h>
#include <sys/sunddi.h>
#include <sys/dmu.h>
@@ -235,6 +233,7 @@ zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain, char **retdomain,
{
fuid_domain_t searchnode, *findnode;
avl_index_t loc;
+ krw_t rw = RW_READER;
/*
* If the dummy "nobody" domain then return an index of 0
@@ -253,11 +252,12 @@ zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain, char **retdomain,
if (!zfsvfs->z_fuid_loaded)
zfs_fuid_init(zfsvfs, tx);
- rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
+retry:
+ rw_enter(&zfsvfs->z_fuid_lock, rw);
findnode = avl_find(&zfsvfs->z_fuid_domain, &searchnode, &loc);
- rw_exit(&zfsvfs->z_fuid_lock);
if (findnode) {
+ rw_exit(&zfsvfs->z_fuid_lock);
ksiddomain_rele(searchnode.f_ksid);
return (findnode->f_idx);
} else {
@@ -270,10 +270,15 @@ zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain, char **retdomain,
dmu_buf_t *db;
int i = 0;
+ if (rw == RW_READER && !rw_tryupgrade(&zfsvfs->z_fuid_lock)) {
+ rw_exit(&zfsvfs->z_fuid_lock);
+ rw = RW_WRITER;
+ goto retry;
+ }
+
domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
domnode->f_ksid = searchnode.f_ksid;
- rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
retidx = domnode->f_idx = avl_numnodes(&zfsvfs->z_fuid_idx) + 1;
avl_add(&zfsvfs->z_fuid_domain, domnode);