mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 10:54:35 +03:00
Add support for rw semaphore under PREEMPT_RT_FULL
The main complication from the RT patch set is that the RW semaphore locks change such that read locks on an rwsem can be taken only by a single thread. All other threads are locked out. This single thread can take a read lock multiple times though. The underlying implementation changes to a mutex with an additional read_depth count. The implementation can be best understood by inspecting the RT patch. rwsem_rt.h and rt.c give the best insight into how RT rwsem works. My implementation for rwsem_tryupgrade is basically an inversion of rt_downgrade_write found in rt.c. Please see the comments in the code. Unfortunately, I have to drop SPLAT rwlock test4 completely as this test tries to take multiple locks from different threads, which RT rwsems do not support. Otherwise SPLAT, zconfig.sh, zpios-sanity.sh and zfs-tests.sh pass on my Debian-testing VM with the kernel linux-image-4.8.0-1-rt-amd64. Tested-by: kernelOfTruth <kerneloftruth@gmail.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Clemens Fruhwirth <clemens@endorphin.org> Closes zfsonlinux/zfs#5491 Closes #589 Closes #308
This commit is contained in:
committed by
Brian Behlendorf
parent
6d064f7a07
commit
8e99d66b05
@@ -106,6 +106,17 @@ void splat_init_rw_priv(rw_priv_t *rwp, struct file *file)
|
||||
rwp->rw_type = 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PREEMPT_RT_FULL)
|
||||
static int
|
||||
splat_rwlock_test1(struct file *file, void *arg)
|
||||
{
|
||||
/*
|
||||
* This test will never succeed on PREEMPT_RT_FULL because these
|
||||
* kernels only allow a single thread to hold the lock.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
splat_rwlock_wr_thr(void *arg)
|
||||
{
|
||||
@@ -297,6 +308,7 @@ splat_rwlock_test1(struct file *file, void *arg)
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
splat_rwlock_test2_func(void *arg)
|
||||
@@ -514,11 +526,22 @@ splat_rwlock_test4(struct file *file, void *arg)
|
||||
|
||||
splat_init_rw_priv(rwp, file);
|
||||
|
||||
/* Validate all combinations of rw_tryenter() contention */
|
||||
/*
|
||||
* Validate all combinations of rw_tryenter() contention.
|
||||
*
|
||||
* The concurrent reader test is modified for PREEMPT_RT_FULL
|
||||
* kernels which do not permit concurrent read locks to be taken
|
||||
* from different threads. The same thread is allowed to take
|
||||
* the read lock multiple times.
|
||||
*/
|
||||
rc1 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_WRITER, RW_WRITER);
|
||||
rc2 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_WRITER, RW_READER);
|
||||
rc3 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_READER, RW_WRITER);
|
||||
#if defined(CONFIG_PREEMPT_RT_FULL)
|
||||
rc4 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_READER, RW_READER);
|
||||
#else
|
||||
rc4 = splat_rwlock_test4_type(tq, rwp, 0, RW_READER, RW_READER);
|
||||
#endif
|
||||
rc5 = splat_rwlock_test4_type(tq, rwp, 0, RW_NONE, RW_WRITER);
|
||||
rc6 = splat_rwlock_test4_type(tq, rwp, 0, RW_NONE, RW_READER);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user