Skip to content

Commit

Permalink
Linux 5.2 compat: rw_tryupgrade()
Browse files Browse the repository at this point in the history
Commit torvalds/linux@46ad0840b has removed the architecture specific
rwsem source and headers leaving only the generic version.  As part
of this change the RWSEM_ACTIVE_READ_BIAS and RWSEM_ACTIVE_WRITE_BIAS
macros were moved to the private kernel/locking/rwsem.h header.
This results in a build failure because these macros were required
to implement the rw_tryupgrade() compatibility function.

In practice, this isn't a major problem because there are only a
few consumers of rw_tryupgrade() and because consumers of rw_tryupgrade
should be written to retry using rw_enter(RW_WRITER).

After auditing all of the callers only dmu_zfetch() was determined
not to perform a retry.  It has been updated in this commit to
resolve this issue.

That said, the rw_tryupgrade() functionality should be considered
for possible removal in a future release due to the difficultly
in supporting the interface.

Reviewed-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
Reviewed-by: Chunwei Chen <tuxoko@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes openzfs#8730
  • Loading branch information
behlendorf authored and allanjude committed Jun 15, 2019
1 parent fa2467d commit 9d7b040
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 5 deletions.
2 changes: 1 addition & 1 deletion include/os/linux/spl/sys/rwlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion module/os/linux/spl/spl-rwlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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)
Expand Down
13 changes: 10 additions & 3 deletions module/zfs/dmu_zfetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 9d7b040

Please sign in to comment.