xref: /openbmc/linux/include/linux/mmap_lock.h (revision 90717566)
19740ca4eSMichel Lespinasse #ifndef _LINUX_MMAP_LOCK_H
29740ca4eSMichel Lespinasse #define _LINUX_MMAP_LOCK_H
39740ca4eSMichel Lespinasse 
42b5067a8SAxel Rasmussen #include <linux/lockdep.h>
52b5067a8SAxel Rasmussen #include <linux/mm_types.h>
642fc5414SMichel Lespinasse #include <linux/mmdebug.h>
72b5067a8SAxel Rasmussen #include <linux/rwsem.h>
82b5067a8SAxel Rasmussen #include <linux/tracepoint-defs.h>
92b5067a8SAxel Rasmussen #include <linux/types.h>
1042fc5414SMichel Lespinasse 
1114c3656bSMichel Lespinasse #define MMAP_LOCK_INITIALIZER(name) \
12da1c55f1SMichel Lespinasse 	.mmap_lock = __RWSEM_INITIALIZER((name).mmap_lock),
1314c3656bSMichel Lespinasse 
142b5067a8SAxel Rasmussen DECLARE_TRACEPOINT(mmap_lock_start_locking);
152b5067a8SAxel Rasmussen DECLARE_TRACEPOINT(mmap_lock_acquire_returned);
162b5067a8SAxel Rasmussen DECLARE_TRACEPOINT(mmap_lock_released);
172b5067a8SAxel Rasmussen 
182b5067a8SAxel Rasmussen #ifdef CONFIG_TRACING
192b5067a8SAxel Rasmussen 
202b5067a8SAxel Rasmussen void __mmap_lock_do_trace_start_locking(struct mm_struct *mm, bool write);
212b5067a8SAxel Rasmussen void __mmap_lock_do_trace_acquire_returned(struct mm_struct *mm, bool write,
222b5067a8SAxel Rasmussen 					   bool success);
232b5067a8SAxel Rasmussen void __mmap_lock_do_trace_released(struct mm_struct *mm, bool write);
242b5067a8SAxel Rasmussen 
__mmap_lock_trace_start_locking(struct mm_struct * mm,bool write)252b5067a8SAxel Rasmussen static inline void __mmap_lock_trace_start_locking(struct mm_struct *mm,
262b5067a8SAxel Rasmussen 						   bool write)
272b5067a8SAxel Rasmussen {
282b5067a8SAxel Rasmussen 	if (tracepoint_enabled(mmap_lock_start_locking))
292b5067a8SAxel Rasmussen 		__mmap_lock_do_trace_start_locking(mm, write);
302b5067a8SAxel Rasmussen }
312b5067a8SAxel Rasmussen 
__mmap_lock_trace_acquire_returned(struct mm_struct * mm,bool write,bool success)322b5067a8SAxel Rasmussen static inline void __mmap_lock_trace_acquire_returned(struct mm_struct *mm,
332b5067a8SAxel Rasmussen 						      bool write, bool success)
342b5067a8SAxel Rasmussen {
352b5067a8SAxel Rasmussen 	if (tracepoint_enabled(mmap_lock_acquire_returned))
362b5067a8SAxel Rasmussen 		__mmap_lock_do_trace_acquire_returned(mm, write, success);
372b5067a8SAxel Rasmussen }
382b5067a8SAxel Rasmussen 
__mmap_lock_trace_released(struct mm_struct * mm,bool write)392b5067a8SAxel Rasmussen static inline void __mmap_lock_trace_released(struct mm_struct *mm, bool write)
402b5067a8SAxel Rasmussen {
412b5067a8SAxel Rasmussen 	if (tracepoint_enabled(mmap_lock_released))
422b5067a8SAxel Rasmussen 		__mmap_lock_do_trace_released(mm, write);
432b5067a8SAxel Rasmussen }
442b5067a8SAxel Rasmussen 
452b5067a8SAxel Rasmussen #else /* !CONFIG_TRACING */
462b5067a8SAxel Rasmussen 
__mmap_lock_trace_start_locking(struct mm_struct * mm,bool write)472b5067a8SAxel Rasmussen static inline void __mmap_lock_trace_start_locking(struct mm_struct *mm,
482b5067a8SAxel Rasmussen 						   bool write)
492b5067a8SAxel Rasmussen {
502b5067a8SAxel Rasmussen }
512b5067a8SAxel Rasmussen 
__mmap_lock_trace_acquire_returned(struct mm_struct * mm,bool write,bool success)522b5067a8SAxel Rasmussen static inline void __mmap_lock_trace_acquire_returned(struct mm_struct *mm,
532b5067a8SAxel Rasmussen 						      bool write, bool success)
542b5067a8SAxel Rasmussen {
552b5067a8SAxel Rasmussen }
562b5067a8SAxel Rasmussen 
__mmap_lock_trace_released(struct mm_struct * mm,bool write)572b5067a8SAxel Rasmussen static inline void __mmap_lock_trace_released(struct mm_struct *mm, bool write)
582b5067a8SAxel Rasmussen {
592b5067a8SAxel Rasmussen }
602b5067a8SAxel Rasmussen 
612b5067a8SAxel Rasmussen #endif /* CONFIG_TRACING */
622b5067a8SAxel Rasmussen 
mmap_assert_locked(struct mm_struct * mm)63438b6e12SSuren Baghdasaryan static inline void mmap_assert_locked(struct mm_struct *mm)
64438b6e12SSuren Baghdasaryan {
65438b6e12SSuren Baghdasaryan 	lockdep_assert_held(&mm->mmap_lock);
66438b6e12SSuren Baghdasaryan 	VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_lock), mm);
67438b6e12SSuren Baghdasaryan }
68438b6e12SSuren Baghdasaryan 
mmap_assert_write_locked(struct mm_struct * mm)69438b6e12SSuren Baghdasaryan static inline void mmap_assert_write_locked(struct mm_struct *mm)
70438b6e12SSuren Baghdasaryan {
71438b6e12SSuren Baghdasaryan 	lockdep_assert_held_write(&mm->mmap_lock);
72438b6e12SSuren Baghdasaryan 	VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_lock), mm);
73438b6e12SSuren Baghdasaryan }
74438b6e12SSuren Baghdasaryan 
755e31275cSSuren Baghdasaryan #ifdef CONFIG_PER_VMA_LOCK
76*90717566SJann Horn /*
77*90717566SJann Horn  * Drop all currently-held per-VMA locks.
78*90717566SJann Horn  * This is called from the mmap_lock implementation directly before releasing
79*90717566SJann Horn  * a write-locked mmap_lock (or downgrading it to read-locked).
80*90717566SJann Horn  * This should normally NOT be called manually from other places.
81*90717566SJann Horn  * If you want to call this manually anyway, keep in mind that this will release
82*90717566SJann Horn  * *all* VMA write locks, including ones from further up the stack.
83*90717566SJann Horn  */
vma_end_write_all(struct mm_struct * mm)845e31275cSSuren Baghdasaryan static inline void vma_end_write_all(struct mm_struct *mm)
855e31275cSSuren Baghdasaryan {
865e31275cSSuren Baghdasaryan 	mmap_assert_write_locked(mm);
87b1f02b95SJann Horn 	/*
88b1f02b95SJann Horn 	 * Nobody can concurrently modify mm->mm_lock_seq due to exclusive
89b1f02b95SJann Horn 	 * mmap_lock being held.
90b1f02b95SJann Horn 	 * We need RELEASE semantics here to ensure that preceding stores into
91b1f02b95SJann Horn 	 * the VMA take effect before we unlock it with this store.
92b1f02b95SJann Horn 	 * Pairs with ACQUIRE semantics in vma_start_read().
93b1f02b95SJann Horn 	 */
94b1f02b95SJann Horn 	smp_store_release(&mm->mm_lock_seq, mm->mm_lock_seq + 1);
955e31275cSSuren Baghdasaryan }
965e31275cSSuren Baghdasaryan #else
vma_end_write_all(struct mm_struct * mm)975e31275cSSuren Baghdasaryan static inline void vma_end_write_all(struct mm_struct *mm) {}
985e31275cSSuren Baghdasaryan #endif
995e31275cSSuren Baghdasaryan 
mmap_init_lock(struct mm_struct * mm)1009740ca4eSMichel Lespinasse static inline void mmap_init_lock(struct mm_struct *mm)
1019740ca4eSMichel Lespinasse {
102da1c55f1SMichel Lespinasse 	init_rwsem(&mm->mmap_lock);
1039740ca4eSMichel Lespinasse }
1049740ca4eSMichel Lespinasse 
mmap_write_lock(struct mm_struct * mm)1059740ca4eSMichel Lespinasse static inline void mmap_write_lock(struct mm_struct *mm)
1069740ca4eSMichel Lespinasse {
1072b5067a8SAxel Rasmussen 	__mmap_lock_trace_start_locking(mm, true);
108da1c55f1SMichel Lespinasse 	down_write(&mm->mmap_lock);
1092b5067a8SAxel Rasmussen 	__mmap_lock_trace_acquire_returned(mm, true, true);
1109740ca4eSMichel Lespinasse }
1119740ca4eSMichel Lespinasse 
mmap_write_lock_nested(struct mm_struct * mm,int subclass)112aaa2cc56SMichel Lespinasse static inline void mmap_write_lock_nested(struct mm_struct *mm, int subclass)
113aaa2cc56SMichel Lespinasse {
1142b5067a8SAxel Rasmussen 	__mmap_lock_trace_start_locking(mm, true);
115da1c55f1SMichel Lespinasse 	down_write_nested(&mm->mmap_lock, subclass);
1162b5067a8SAxel Rasmussen 	__mmap_lock_trace_acquire_returned(mm, true, true);
117aaa2cc56SMichel Lespinasse }
118aaa2cc56SMichel Lespinasse 
mmap_write_lock_killable(struct mm_struct * mm)1199740ca4eSMichel Lespinasse static inline int mmap_write_lock_killable(struct mm_struct *mm)
1209740ca4eSMichel Lespinasse {
1212b5067a8SAxel Rasmussen 	int ret;
1222b5067a8SAxel Rasmussen 
1232b5067a8SAxel Rasmussen 	__mmap_lock_trace_start_locking(mm, true);
1242b5067a8SAxel Rasmussen 	ret = down_write_killable(&mm->mmap_lock);
1252b5067a8SAxel Rasmussen 	__mmap_lock_trace_acquire_returned(mm, true, ret == 0);
1262b5067a8SAxel Rasmussen 	return ret;
1279740ca4eSMichel Lespinasse }
1289740ca4eSMichel Lespinasse 
mmap_write_unlock(struct mm_struct * mm)1299740ca4eSMichel Lespinasse static inline void mmap_write_unlock(struct mm_struct *mm)
1309740ca4eSMichel Lespinasse {
1312b5067a8SAxel Rasmussen 	__mmap_lock_trace_released(mm, true);
1325e31275cSSuren Baghdasaryan 	vma_end_write_all(mm);
13310994316SLiam Howlett 	up_write(&mm->mmap_lock);
1349740ca4eSMichel Lespinasse }
1359740ca4eSMichel Lespinasse 
mmap_write_downgrade(struct mm_struct * mm)1369740ca4eSMichel Lespinasse static inline void mmap_write_downgrade(struct mm_struct *mm)
1379740ca4eSMichel Lespinasse {
1382b5067a8SAxel Rasmussen 	__mmap_lock_trace_acquire_returned(mm, false, true);
1395e31275cSSuren Baghdasaryan 	vma_end_write_all(mm);
14010994316SLiam Howlett 	downgrade_write(&mm->mmap_lock);
1419740ca4eSMichel Lespinasse }
1429740ca4eSMichel Lespinasse 
mmap_read_lock(struct mm_struct * mm)1439740ca4eSMichel Lespinasse static inline void mmap_read_lock(struct mm_struct *mm)
1449740ca4eSMichel Lespinasse {
1452b5067a8SAxel Rasmussen 	__mmap_lock_trace_start_locking(mm, false);
146da1c55f1SMichel Lespinasse 	down_read(&mm->mmap_lock);
1472b5067a8SAxel Rasmussen 	__mmap_lock_trace_acquire_returned(mm, false, true);
1489740ca4eSMichel Lespinasse }
1499740ca4eSMichel Lespinasse 
mmap_read_lock_killable(struct mm_struct * mm)1509740ca4eSMichel Lespinasse static inline int mmap_read_lock_killable(struct mm_struct *mm)
1519740ca4eSMichel Lespinasse {
1522b5067a8SAxel Rasmussen 	int ret;
1532b5067a8SAxel Rasmussen 
1542b5067a8SAxel Rasmussen 	__mmap_lock_trace_start_locking(mm, false);
1552b5067a8SAxel Rasmussen 	ret = down_read_killable(&mm->mmap_lock);
1562b5067a8SAxel Rasmussen 	__mmap_lock_trace_acquire_returned(mm, false, ret == 0);
1572b5067a8SAxel Rasmussen 	return ret;
1589740ca4eSMichel Lespinasse }
1599740ca4eSMichel Lespinasse 
mmap_read_trylock(struct mm_struct * mm)1609740ca4eSMichel Lespinasse static inline bool mmap_read_trylock(struct mm_struct *mm)
1619740ca4eSMichel Lespinasse {
1622b5067a8SAxel Rasmussen 	bool ret;
1632b5067a8SAxel Rasmussen 
1642b5067a8SAxel Rasmussen 	__mmap_lock_trace_start_locking(mm, false);
1652b5067a8SAxel Rasmussen 	ret = down_read_trylock(&mm->mmap_lock) != 0;
1662b5067a8SAxel Rasmussen 	__mmap_lock_trace_acquire_returned(mm, false, ret);
1672b5067a8SAxel Rasmussen 	return ret;
1689740ca4eSMichel Lespinasse }
1699740ca4eSMichel Lespinasse 
mmap_read_unlock(struct mm_struct * mm)1709740ca4eSMichel Lespinasse static inline void mmap_read_unlock(struct mm_struct *mm)
1719740ca4eSMichel Lespinasse {
1722b5067a8SAxel Rasmussen 	__mmap_lock_trace_released(mm, false);
17310994316SLiam Howlett 	up_read(&mm->mmap_lock);
1749740ca4eSMichel Lespinasse }
1759740ca4eSMichel Lespinasse 
mmap_read_unlock_non_owner(struct mm_struct * mm)1760cc55a02SMichel Lespinasse static inline void mmap_read_unlock_non_owner(struct mm_struct *mm)
1770cc55a02SMichel Lespinasse {
1782b5067a8SAxel Rasmussen 	__mmap_lock_trace_released(mm, false);
17910994316SLiam Howlett 	up_read_non_owner(&mm->mmap_lock);
1800cc55a02SMichel Lespinasse }
1810cc55a02SMichel Lespinasse 
mmap_lock_is_contended(struct mm_struct * mm)18207e5bfe6SChinwen Chang static inline int mmap_lock_is_contended(struct mm_struct *mm)
18307e5bfe6SChinwen Chang {
18407e5bfe6SChinwen Chang 	return rwsem_is_contended(&mm->mmap_lock);
18507e5bfe6SChinwen Chang }
18607e5bfe6SChinwen Chang 
1879740ca4eSMichel Lespinasse #endif /* _LINUX_MMAP_LOCK_H */
188