On Fri, Dec 13, 2024 at 04:04:40PM -0500, Liam R. Howlett wrote: > * Christian Brauner <brauner@xxxxxxxxxx> [241213 15:11]: > > On Fri, Dec 13, 2024 at 08:25:21PM +0100, Christian Brauner wrote: > > > On Fri, Dec 13, 2024 at 08:01:30PM +0100, Christian Brauner wrote: > > > > On Fri, Dec 13, 2024 at 06:53:55PM +0000, Matthew Wilcox wrote: > > > > > On Fri, Dec 13, 2024 at 07:51:50PM +0100, Christian Brauner wrote: > > > > > > Yeah, it does. Did you see the patch that is included in the series? > > > > > > I've replaced the macro with always inline functions that select the > > > > > > lock based on the flag: > > > > > > > > > > > > static __always_inline void mtree_lock(struct maple_tree *mt) > > > > > > { > > > > > > if (mt->ma_flags & MT_FLAGS_LOCK_IRQ) > > > > > > spin_lock_irq(&mt->ma_lock); > > > > > > else > > > > > > spin_lock(&mt->ma_lock); > > > > > > } > > > > > > static __always_inline void mtree_unlock(struct maple_tree *mt) > > > > > > { > > > > > > if (mt->ma_flags & MT_FLAGS_LOCK_IRQ) > > > > > > spin_unlock_irq(&mt->ma_lock); > > > > > > else > > > > > > spin_unlock(&mt->ma_lock); > > > > > > } > > > > > > > > > > > > Does that work for you? > > > > > > > > > > See the way the XArray works; we're trying to keep the two APIs as > > > > > close as possible. > > > > > > > > > > The caller should use mtree_lock_irq() or mtree_lock_irqsave() > > > > > as appropriate. > > > > > > > > Say I need: > > > > > > > > spin_lock_irqsave(&mt->ma_lock, flags); > > > > mas_erase(...); > > > > -> mas_nomem() > > > > -> mtree_unlock() // uses spin_unlock(); > > > > // allocate > > > > -> mtree_lock() // uses spin_lock(); > > > > spin_lock_irqrestore(&mt->ma_lock, flags); > > > > > > > > So that doesn't work, right? IOW, the maple tree does internal drop and > > > > retake locks and they need to match the locks of the outer context. > > > > > > > > So, I think I need a way to communicate to mas_*() what type of lock to > > > > take, no? Any idea how you would like me to do this in case I'm not > > > > wrong? > > > > > > My first inclination has been to do it via MA_STATE() and the mas_flag > > > value but I'm open to any other ideas. > > > > Braino on my part as free_pid() can be called with write_lock_irq() held. > > Instead of checking the flag inside mas_lock()/mas_unlock(), the flag is > checked in mas_nomem(), and the correct mas_lock_irq() pair would be > called there. External callers would use the mas_lock_irq() pair > directly instead of checking the flag. I'm probably being dense but say I have two different locations with two different locking requirements - as is the case with alloc_pid() and free_pid(). alloc_pid() just uses spin_lock_irq() and spin_unlock_irq() but free_pid() requires spin_lock_irqsave() and spin_unlock_irqrestore(). If the whole mtree is marked with a flag that tells the mtree_lock() to use spin_lock_irq() then it will use that also in free_pid() where it should use spin_lock_irqsave(). So if I'm not completely off-track then we'd need a way to tell the mtree to use different locks for different callsites. Or at least override the locking requirements for specific calls by e.g., allowing a flag to be specified in the MA_STATE() struct that's checke by e.g., mas_nomem(). > To keep the API as close as possible, we'd keep the mas_lock() the same > and add the mas_lock_irq() as well as mas_lock_type(mas, lock_type). > __xas_nomem() uses the (static) xas_lock_type() to lock/unlock for > internal translations. > > Thanks, > Liam