diff options
-rw-r--r-- | include/spl/sys/rwlock.h | 2 | ||||
-rw-r--r-- | module/spl/spl-rwlock.c | 10 | ||||
-rw-r--r-- | module/zfs/dmu_zfetch.c | 13 |
3 files changed, 20 insertions, 5 deletions
diff --git a/include/spl/sys/rwlock.h b/include/spl/sys/rwlock.h index a1c1fd469..408defac2 100644 --- a/include/spl/sys/rwlock.h +++ b/include/spl/sys/rwlock.h @@ -36,7 +36,7 @@ #elif defined(CONFIG_RWSEM_GENERIC_SPINLOCK) #define SPL_RWSEM_SINGLE_READER_VALUE (1) #define SPL_RWSEM_SINGLE_WRITER_VALUE (-1) -#else +#elif defined(RWSEM_ACTIVE_MASK) #define SPL_RWSEM_SINGLE_READER_VALUE (RWSEM_ACTIVE_READ_BIAS) #define SPL_RWSEM_SINGLE_WRITER_VALUE (RWSEM_ACTIVE_WRITE_BIAS) #endif diff --git a/module/spl/spl-rwlock.c b/module/spl/spl-rwlock.c index 4ffebc8ea..86727ed19 100644 --- a/module/spl/spl-rwlock.c +++ b/module/spl/spl-rwlock.c @@ -85,7 +85,8 @@ __rwsem_tryupgrade(struct rw_semaphore *rwsem) spl_rwsem_unlock_irqrestore(&rwsem->wait_lock, flags); return (ret); } -#elif defined(HAVE_RWSEM_ATOMIC_LONG_COUNT) +#elif defined(RWSEM_ACTIVE_MASK) +#if defined(HAVE_RWSEM_ATOMIC_LONG_COUNT) static int __rwsem_tryupgrade(struct rw_semaphore *rwsem) { @@ -104,6 +105,13 @@ __rwsem_tryupgrade(struct rw_semaphore *rwsem) return (val == SPL_RWSEM_SINGLE_READER_VALUE); } #endif +#else +static int +__rwsem_tryupgrade(struct rw_semaphore *rwsem) +{ + return (0); +} +#endif int rwsem_tryupgrade(struct rw_semaphore *rwsem) diff --git a/module/zfs/dmu_zfetch.c b/module/zfs/dmu_zfetch.c index 2133518ff..364e4d7aa 100644 --- a/module/zfs/dmu_zfetch.c +++ b/module/zfs/dmu_zfetch.c @@ -214,6 +214,7 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks, boolean_t fetch_data) uint64_t end_of_access_blkid; end_of_access_blkid = blkid + nblks; spa_t *spa = zf->zf_dnode->dn_objset->os_spa; + krw_t rw = RW_READER; if (zfs_prefetch_disable) return; @@ -234,7 +235,8 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks, boolean_t fetch_data) if (blkid == 0) return; - rw_enter(&zf->zf_rwlock, RW_READER); +retry: + rw_enter(&zf->zf_rwlock, rw); /* * Find matching prefetch stream. Depending on whether the accesses @@ -272,8 +274,13 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks, boolean_t fetch_data) * a new stream for it. */ ZFETCHSTAT_BUMP(zfetchstat_misses); - if (rw_tryupgrade(&zf->zf_rwlock)) - dmu_zfetch_stream_create(zf, end_of_access_blkid); + if (rw == RW_READER && !rw_tryupgrade(&zf->zf_rwlock)) { + rw_exit(&zf->zf_rwlock); + rw = RW_WRITER; + goto retry; + } + + dmu_zfetch_stream_create(zf, end_of_access_blkid); rw_exit(&zf->zf_rwlock); return; } |