DF-4329 / fix.diff
--- a/sys/dev/drm/include/linux/rcupdate.h +++ b/sys/dev/drm/include/linux/rcupdate.h @@ -22,6 +22,10 @@ #include <asm/barrier.h> +#include <sys/rcu.h> /* DragonFly's real RCU implementation */ + #include <linux/rcutree.h> -static inline void -rcu_read_lock(void) -{ - preempt_disable(); -} +/* + * Delegate the read side to DragonFly's native RCU, which tracks + * readers so synchronize_rcu() below can actually wait for them. + */ +#define rcu_read_lock() rcu_read_lock_native() +#define rcu_read_unlock() rcu_read_unlock_native() @@ -90,9 +94,14 @@ extern void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *)); #define rcu_access_pointer(p) ((typeof(*p) *)READ_ONCE(p)) -#define synchronize_rcu() -#define cond_synchronize_rcu(x) cpu_mfence() -#define get_state_synchronize_rcu() 0 +/* + * The empty synchronize_rcu() silently broke every lifetime protocol + * in the drm/i915 port that relies on grace periods (e.g. the i915 + * request-object SLAB_TYPESAFE_BY_RCU reuse protocol in + * i915_request.c / i915_request.h). Map them onto the native + * implementation. (Namespaced to avoid colliding with the native + * prototypes.) + */ +#define synchronize_rcu() synchronize_rcu_native() +#define cond_synchronize_rcu(x) do { synchronize_rcu_native(); (void)(x); } while (0) +#define get_state_synchronize_rcu() get_state_synchronize_rcu_native() #endif /* _LINUX_RCUPDATE_H_ */ --- a/sys/dev/drm/include/linux/dma-fence.h +++ b/sys/dev/drm/include/linux/dma-fence.h @@ -95,11 +95,17 @@ struct dma_fence { static inline struct dma_fence * dma_fence_get_rcu(struct dma_fence *fence) { if (fence) - kref_get(&fence->refcount); + /* + * The _rcu variant is used by lockless readers that may + * race the fence's release: an unconditional increment + * RESURRECTS a freed fence (0 -> 1) and corrupts + * whatever now owns that memory. Upstream semantics: + * refuse unless the refcount is live. + */ + if (!kref_get_unless_zero(&fence->refcount)) + return NULL; return fence; } |