-#define rw_tryupgrade(rwp) \
-({ \
- unsigned long _flags_; \
- int _rc_ = 0; \
- \
- spin_lock_irqsave(&SEM(rwp)->wait_lock, _flags_); \
- if (list_empty(&SEM(rwp)->wait_list) && (RW_COUNT(rwp) == 1)) { \
- rw_exit_locked(SEM(rwp)); \
- VERIFY(_rc_ = rw_tryenter_locked(SEM(rwp))); \
- (rwp)->rw_owner = current; \
- } \
- spin_unlock_irqrestore(&SEM(rwp)->wait_lock, _flags_); \
- _rc_; \
+/*
+ * This implementation of rw_tryupgrade() behaves slightly differently
+ * from its counterparts on other platforms. It drops the RW_READER lock
+ * and then acquires the RW_WRITER lock leaving a small window where no
+ * lock is held. On other platforms the lock is never released during
+ * the upgrade process. This is necessary under Linux because the kernel
+ * does not provide an upgrade function.
+ */
+#define rw_tryupgrade(rwp) \
+({ \
+ int _rc_ = 0; \
+ \
+ if (RW_WRITE_HELD(rwp)) { \
+ _rc_ = 1; \
+ } else { \
+ spl_rw_lockdep_off_maybe(rwp); \
+ if ((_rc_ = rwsem_tryupgrade(SEM(rwp)))) \
+ spl_rw_set_owner(rwp); \
+ spl_rw_lockdep_on_maybe(rwp); \
+ } \
+ _rc_; \