diff options
author | Mark Shellenbaum <Mark.Shellenbaum@Sun.COM> | 2008-08-18 12:57:21 -0600 |
---|---|---|
committer | Mark Shellenbaum <Mark.Shellenbaum@Sun.COM> | 2008-08-18 12:57:21 -0600 |
commit | a078ff4a0f321365c3ca4cd812df95c377f50916 (patch) | |
tree | 408f27b450f15935c9271bc7d027c2f98082b607 /usr/src | |
parent | 9e42605d62761d569868c10ca9f2041b6d58d0d6 (diff) | |
download | illumos-joyent-a078ff4a0f321365c3ca4cd812df95c377f50916.tar.gz |
6737346 zfs_fuid_find_by_domain() has locking issue
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_fuid.c | 15 |
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); |