On Thu, Feb 27, 2020 at 09:36:33PM +0100, Pavel Reichl wrote: > Refactor xfs_isilocked() to use newly introduced __xfs_rwsem_islocked(). > __xfs_rwsem_islocked() is a helper function which encapsulates checking > state of rw_semaphores hold by inode. > > Signed-off-by: Pavel Reichl <preichl@xxxxxxxxxx> > Suggested-by: Dave Chinner <dchinner@xxxxxxxxxx> > Suggested-by: Eric Sandeen <sandeen@xxxxxxxxxx> > --- > Changes from V5: > Drop shared flag from __xfs_rwsem_islocked() > > > fs/xfs/xfs_inode.c | 42 ++++++++++++++++++++++++++---------------- > fs/xfs/xfs_inode.h | 2 +- > 2 files changed, 27 insertions(+), 17 deletions(-) > > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c > index c5077e6326c7..4faf7827717b 100644 > --- a/fs/xfs/xfs_inode.c > +++ b/fs/xfs/xfs_inode.c > @@ -345,32 +345,42 @@ xfs_ilock_demote( > } > > #if defined(DEBUG) || defined(XFS_WARN) > -int > +static inline bool > +__xfs_rwsem_islocked( > + struct rw_semaphore *rwsem, > + bool excl) > +{ > + if (!rwsem_is_locked(rwsem)) > + return false; So, uh, I finally made the time to dig through what exactly lockdep provides as far as testing functions, and came up with the following truth table for the old xfs_isilocked behavior w.r.t. IOLOCK: (nolockdep corresponds to debug_locks == 0) RWSEM STATE PARAMETERS TO XFS_ISILOCKED: SHARED EXCL SHARED | EXCL readlocked y n y writelocked y y y unlocked n n n nolockdep readlocked y y y nolockdep writelocked y y y nolockdep unlocked n y n Note that EXCL × nolockdep_unlocked returns an incorrect result, but because we only use it with ASSERTs there haven't been any failures reported. And here's your new version: readlocked y y y writelocked y n n unlocked n n n nolockdep readlocked y y y nolockdep writelocked y y y nolockdep unlocked n n n Thanks for fixing the false positive that I mentioned above. > + > + if (debug_locks && excl) > + return lockdep_is_held_type(rwsem, 1); This is wrong, the second parameter of lockdep_is_held_type is 0 to test if the rwsem is write-locked; 1 to test if it is read-locked; or -1 to test if the rwsem is read or write-locked. So, this function's call signature should change so that callers can communicate both _SHARED and _EXCL; and then you can pick the correct "r" parameter value for the lockdep_is_held_type() call. Then all of this becomes: if !debug_locks: return rwsem_is_locked(rwsem) if shared and excl: r = -1 elif shared: r = 1 else: r = 0 return lockdep_is_held_type(rwsem, r) Note also that you don't necessarily need to pass shared and excl as separate parameters (as you did in v3); the XFS_*LOCK_{EXCL,SHARED} definitions enable you to take care of all that with some clever bit shifting and masking. --D > + > + return true; > +} > + > +bool > xfs_isilocked( > - xfs_inode_t *ip, > + struct xfs_inode *ip, > uint lock_flags) > { > - if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) { > - if (!(lock_flags & XFS_ILOCK_SHARED)) > - return !!ip->i_lock.mr_writer; > - return rwsem_is_locked(&ip->i_lock.mr_lock); > + if (lock_flags & (XFS_ILOCK_EXCL | XFS_ILOCK_SHARED)) { > + return __xfs_rwsem_islocked(&ip->i_lock.mr_lock, > + (lock_flags & XFS_ILOCK_EXCL)); > } > > - if (lock_flags & (XFS_MMAPLOCK_EXCL|XFS_MMAPLOCK_SHARED)) { > - if (!(lock_flags & XFS_MMAPLOCK_SHARED)) > - return !!ip->i_mmaplock.mr_writer; > - return rwsem_is_locked(&ip->i_mmaplock.mr_lock); > + if (lock_flags & (XFS_MMAPLOCK_EXCL | XFS_MMAPLOCK_SHARED)) { > + return __xfs_rwsem_islocked(&ip->i_mmaplock.mr_lock, > + (lock_flags & XFS_MMAPLOCK_EXCL)); > } > > - if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) { > - if (!(lock_flags & XFS_IOLOCK_SHARED)) > - return !debug_locks || > - lockdep_is_held_type(&VFS_I(ip)->i_rwsem, 0); > - return rwsem_is_locked(&VFS_I(ip)->i_rwsem); > + if (lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) { > + return __xfs_rwsem_islocked(&VFS_I(ip)->i_rwsem, > + (lock_flags & XFS_IOLOCK_EXCL)); > } > > ASSERT(0); > - return 0; > + return false; > } > #endif > > diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h > index 492e53992fa9..3d7ce355407d 100644 > --- a/fs/xfs/xfs_inode.h > +++ b/fs/xfs/xfs_inode.h > @@ -416,7 +416,7 @@ void xfs_ilock(xfs_inode_t *, uint); > int xfs_ilock_nowait(xfs_inode_t *, uint); > void xfs_iunlock(xfs_inode_t *, uint); > void xfs_ilock_demote(xfs_inode_t *, uint); > -int xfs_isilocked(xfs_inode_t *, uint); > +bool xfs_isilocked(xfs_inode_t *, uint); > uint xfs_ilock_data_map_shared(struct xfs_inode *); > uint xfs_ilock_attr_map_shared(struct xfs_inode *); > > -- > 2.24.1 >