On Wed, Apr 14, 2021 at 10:01:13AM +1000, Dave Chinner wrote: > > + if (iocb->ki_flags & IOCB_NOWAIT) { > > + if (!down_read_trylock(&mapping->host->i_mapping_sem)) > > + return -EAGAIN; > > + } else { > > + down_read(&mapping->host->i_mapping_sem); > > + } > > We really need a lock primitive for this. The number of times this > exact lock pattern is being replicated all through the IO path is > getting out of hand. > > static inline bool > down_read_try_or_lock(struct rwsem *sem, bool try) > { > if (try) { > if (!down_read_trylock(sem)) > return false; > } else { > down_read(&mapping->host->i_mapping_sem); > } > return true; > } > > and the callers become: > > if (!down_read_try_or_lock(sem, (iocb->ki_flags & IOCB_NOWAIT))) > return -EAGAIN; I think that should be written: if (!iocb_read_lock(iocb, &rwsem)) return -EAGAIN; and implemented as: static inline int iocb_read_lock(struct kiocb *iocb, struct rwsem *sem) { if (iocb->ki_flags & IOCB_NOWAIT) return down_read_trylock(sem) ? 0 : -EAGAIN; return down_read_killable(sem); }