Linux 5.3 compat: rw_semaphore owner
Commit https://github.com/torvalds/linux/commit/94a9717b updated the rwsem's owner field to contain additional flags describing the rwsem's state. Rather then update the wrappers to mask out these bits, the code no longer relies on the owner stored by the kernel. This does increase the size of a krwlock_t but it makes the implementation less sensitive to future kernel changes. Reviewed-by: Tony Hutter <hutter2@llnl.gov> Reviewed-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #9029
This commit is contained in:
parent
a649768a17
commit
041205afee
|
@ -78,15 +78,9 @@ typedef enum {
|
||||||
RW_READER = 2
|
RW_READER = 2
|
||||||
} krw_t;
|
} krw_t;
|
||||||
|
|
||||||
/*
|
|
||||||
* If CONFIG_RWSEM_SPIN_ON_OWNER is defined, rw_semaphore will have an owner
|
|
||||||
* field, so we don't need our own.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct rw_semaphore rw_rwlock;
|
struct rw_semaphore rw_rwlock;
|
||||||
#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
|
|
||||||
kthread_t *rw_owner;
|
kthread_t *rw_owner;
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_LOCKDEP
|
#ifdef CONFIG_LOCKDEP
|
||||||
krw_type_t rw_type;
|
krw_type_t rw_type;
|
||||||
#endif /* CONFIG_LOCKDEP */
|
#endif /* CONFIG_LOCKDEP */
|
||||||
|
@ -97,31 +91,19 @@ typedef struct {
|
||||||
static inline void
|
static inline void
|
||||||
spl_rw_set_owner(krwlock_t *rwp)
|
spl_rw_set_owner(krwlock_t *rwp)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* If CONFIG_RWSEM_SPIN_ON_OWNER is defined, down_write, up_write,
|
|
||||||
* downgrade_write and __init_rwsem will set/clear owner for us.
|
|
||||||
*/
|
|
||||||
#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
|
|
||||||
rwp->rw_owner = current;
|
rwp->rw_owner = current;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
spl_rw_clear_owner(krwlock_t *rwp)
|
spl_rw_clear_owner(krwlock_t *rwp)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
|
|
||||||
rwp->rw_owner = NULL;
|
rwp->rw_owner = NULL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline kthread_t *
|
static inline kthread_t *
|
||||||
rw_owner(krwlock_t *rwp)
|
rw_owner(krwlock_t *rwp)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
|
|
||||||
return (SEM(rwp)->owner);
|
|
||||||
#else
|
|
||||||
return (rwp->rw_owner);
|
return (rwp->rw_owner);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_LOCKDEP
|
#ifdef CONFIG_LOCKDEP
|
||||||
|
@ -148,6 +130,11 @@ spl_rw_lockdep_on_maybe(krwlock_t *rwp) \
|
||||||
#define spl_rw_lockdep_on_maybe(rwp)
|
#define spl_rw_lockdep_on_maybe(rwp)
|
||||||
#endif /* CONFIG_LOCKDEP */
|
#endif /* CONFIG_LOCKDEP */
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
RW_LOCK_HELD(krwlock_t *rwp)
|
||||||
|
{
|
||||||
|
return (spl_rwsem_is_locked(SEM(rwp)));
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
RW_WRITE_HELD(krwlock_t *rwp)
|
RW_WRITE_HELD(krwlock_t *rwp)
|
||||||
|
@ -155,55 +142,10 @@ RW_WRITE_HELD(krwlock_t *rwp)
|
||||||
return (rw_owner(rwp) == current);
|
return (rw_owner(rwp) == current);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
|
||||||
RW_LOCK_HELD(krwlock_t *rwp)
|
|
||||||
{
|
|
||||||
return (spl_rwsem_is_locked(SEM(rwp)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
RW_READ_HELD(krwlock_t *rwp)
|
RW_READ_HELD(krwlock_t *rwp)
|
||||||
{
|
{
|
||||||
if (!RW_LOCK_HELD(rwp))
|
return (RW_LOCK_HELD(rwp) && rw_owner(rwp) == NULL);
|
||||||
return (0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rw_semaphore cheat sheet:
|
|
||||||
*
|
|
||||||
* < 3.16:
|
|
||||||
* There's no rw_semaphore.owner, so use rwp.owner instead.
|
|
||||||
* If rwp.owner == NULL then it's a reader
|
|
||||||
*
|
|
||||||
* 3.16 - 4.7:
|
|
||||||
* rw_semaphore.owner added (https://lwn.net/Articles/596656/)
|
|
||||||
* and CONFIG_RWSEM_SPIN_ON_OWNER introduced.
|
|
||||||
* If rw_semaphore.owner == NULL then it's a reader
|
|
||||||
*
|
|
||||||
* 4.8 - 4.16.16:
|
|
||||||
* RWSEM_READER_OWNED added as an internal #define.
|
|
||||||
* (https://lore.kernel.org/patchwork/patch/678590/)
|
|
||||||
* If rw_semaphore.owner == 1 then it's a reader
|
|
||||||
*
|
|
||||||
* 4.16.17 - 4.19:
|
|
||||||
* RWSEM_OWNER_UNKNOWN introduced as ((struct task_struct *)-1L)
|
|
||||||
* (https://do-db2.lkml.org/lkml/2018/5/15/985)
|
|
||||||
* If rw_semaphore.owner == 1 then it's a reader.
|
|
||||||
*
|
|
||||||
* 4.20+:
|
|
||||||
* RWSEM_OWNER_UNKNOWN changed to ((struct task_struct *)-2L)
|
|
||||||
* (https://lkml.org/lkml/2018/9/6/986)
|
|
||||||
* If rw_semaphore.owner & 1 then it's a reader, and also the reader's
|
|
||||||
* task_struct may be embedded in rw_semaphore->owner.
|
|
||||||
*/
|
|
||||||
#if defined(CONFIG_RWSEM_SPIN_ON_OWNER) && defined(RWSEM_OWNER_UNKNOWN)
|
|
||||||
if (RWSEM_OWNER_UNKNOWN == (struct task_struct *)-2L) {
|
|
||||||
/* 4.20+ kernels with CONFIG_RWSEM_SPIN_ON_OWNER */
|
|
||||||
return ((unsigned long) SEM(rwp)->owner & 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* < 4.20 kernel or !CONFIG_RWSEM_SPIN_ON_OWNER */
|
|
||||||
return (rw_owner(rwp) == NULL || (unsigned long) rw_owner(rwp) == 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -119,9 +119,6 @@ rwsem_tryupgrade(struct rw_semaphore *rwsem)
|
||||||
if (__rwsem_tryupgrade(rwsem)) {
|
if (__rwsem_tryupgrade(rwsem)) {
|
||||||
rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
|
rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
|
||||||
rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
|
rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
|
||||||
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
|
|
||||||
rwsem->owner = current;
|
|
||||||
#endif
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
|
|
Loading…
Reference in New Issue