* the owner value concurrently without lock. Read from owner, however,
  * may not need READ_ONCE() as long as the pointer value is only used
  * for comparison and isn't being dereferenced.
+ *
+ * Both rwsem_{set,clear}_owner() functions should be in the same
+ * preempt disable section as the atomic op that changes sem->count.
  */
 static inline void rwsem_set_owner(struct rw_semaphore *sem)
 {
+       lockdep_assert_preemption_disabled();
        atomic_long_set(&sem->owner, (long)current);
 }
 
 static inline void rwsem_clear_owner(struct rw_semaphore *sem)
 {
+       lockdep_assert_preemption_disabled();
        atomic_long_set(&sem->owner, 0);
 }
 
 static inline bool rwsem_write_trylock(struct rw_semaphore *sem)
 {
        long tmp = RWSEM_UNLOCKED_VALUE;
+       bool ret = false;
 
+       preempt_disable();
        if (atomic_long_try_cmpxchg_acquire(&sem->count, &tmp, RWSEM_WRITER_LOCKED)) {
                rwsem_set_owner(sem);
-               return true;
+               ret = true;
        }
 
-       return false;
+       preempt_enable();
+       return ret;
 }
 
 /*
        DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) &&
                            !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE), sem);
 
+       preempt_disable();
        rwsem_clear_owner(sem);
        tmp = atomic_long_fetch_add_release(-RWSEM_WRITER_LOCKED, &sem->count);
+       preempt_enable();
        if (unlikely(tmp & RWSEM_FLAG_WAITERS))
                rwsem_wake(sem);
 }