xfs: grab dquots without taking the ilock
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 27 Jun 2017 17:19:45 +0000 (10:19 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 28 Jun 2017 01:23:22 +0000 (18:23 -0700)
Add a new dqget flag that grabs the dquot without taking the ilock.
This will be used by the scrubber (which will have already grabbed
the ilock) to perform basic sanity checking of the quota data.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
fs/xfs/libxfs/xfs_quota_defs.h
fs/xfs/xfs_dquot.c

index d69c772271cb0d882ceabbc0b5754c94ec4d5367..2834574cb6e7d8f72ce1c00fef360edb45894f1e 100644 (file)
@@ -136,6 +136,8 @@ typedef uint16_t    xfs_qwarncnt_t;
  */
 #define XFS_QMOPT_INHERIT      0x1000000
 
+#define XFS_QMOPT_NOLOCK       0x2000000 /* don't ilock during dqget */
+
 /*
  * flags to xfs_trans_mod_dquot.
  */
index e57c6cce91aaba37ff7ed1323fe63027d5a86c2e..79668142afc1febc99c7eefc373734ff21330966 100644 (file)
@@ -472,18 +472,23 @@ xfs_qm_dqtobp(
        struct xfs_mount        *mp = dqp->q_mount;
        xfs_dqid_t              id = be32_to_cpu(dqp->q_core.d_id);
        struct xfs_trans        *tp = (tpp ? *tpp : NULL);
-       uint                    lock_mode;
+       uint                    lock_mode = 0;
 
        quotip = xfs_quota_inode(dqp->q_mount, dqp->dq_flags);
        dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
 
-       lock_mode = xfs_ilock_data_map_shared(quotip);
+       ASSERT(!(flags & XFS_QMOPT_NOLOCK) ||
+               xfs_isilocked(quotip, XFS_ILOCK_SHARED) ||
+               xfs_isilocked(quotip, XFS_ILOCK_EXCL));
+       if (!(flags & XFS_QMOPT_NOLOCK))
+               lock_mode = xfs_ilock_data_map_shared(quotip);
        if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) {
                /*
                 * Return if this type of quotas is turned off while we
                 * didn't have the quota inode lock.
                 */
-               xfs_iunlock(quotip, lock_mode);
+               if (lock_mode)
+                       xfs_iunlock(quotip, lock_mode);
                return -ESRCH;
        }
 
@@ -493,7 +498,8 @@ xfs_qm_dqtobp(
        error = xfs_bmapi_read(quotip, dqp->q_fileoffset,
                               XFS_DQUOT_CLUSTER_SIZE_FSB, &map, &nmaps, 0);
 
-       xfs_iunlock(quotip, lock_mode);
+       if (lock_mode)
+               xfs_iunlock(quotip, lock_mode);
        if (error)
                return error;