int                     wantoff;        /* starting block offset */
        xfs_off_t               cook;
        struct xfs_da_geometry  *geo = args->geo;
+       int                     lock_mode;
 
        /*
         * If the block number in the offset is out of range, we're done.
        if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk)
                return 0;
 
+       lock_mode = xfs_ilock_data_map_shared(dp);
        error = xfs_dir3_block_read(NULL, dp, &bp);
+       xfs_iunlock(dp, lock_mode);
        if (error)
                return error;
 
                 * current buffer, need to get another one.
                 */
                if (!bp || ptr >= (char *)bp->b_addr + geo->blksize) {
+                       int     lock_mode;
 
+                       lock_mode = xfs_ilock_data_map_shared(dp);
                        error = xfs_dir2_leaf_readbuf(args, bufsize, map_info,
                                                      &curoff, &bp);
+                       xfs_iunlock(dp, lock_mode);
                        if (error || !map_info->map_valid)
                                break;
 
        struct xfs_da_args      args = { NULL };
        int                     rval;
        int                     v;
-       uint                    lock_mode;
 
        trace_xfs_readdir(dp);
 
        args.dp = dp;
        args.geo = dp->i_mount->m_dir_geo;
 
-       lock_mode = xfs_ilock_data_map_shared(dp);
+       xfs_ilock(dp, XFS_IOLOCK_SHARED);
        if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
                rval = xfs_dir2_sf_getdents(&args, ctx);
        else if ((rval = xfs_dir2_isblock(&args, &v)))
                rval = xfs_dir2_block_getdents(&args, ctx);
        else
                rval = xfs_dir2_leaf_getdents(&args, ctx, bufsize);
-       xfs_iunlock(dp, lock_mode);
+       xfs_iunlock(dp, XFS_IOLOCK_SHARED);
 
        return rval;
 }
 
 {
        xfs_ino_t               inum;
        int                     error;
-       uint                    lock_mode;
 
        trace_xfs_lookup(dp, name);
 
        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
                return -EIO;
 
-       lock_mode = xfs_ilock_data_map_shared(dp);
+       xfs_ilock(dp, XFS_IOLOCK_SHARED);
        error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name);
-       xfs_iunlock(dp, lock_mode);
-
        if (error)
-               goto out;
+               goto out_unlock;
 
        error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp);
        if (error)
                goto out_free_name;
 
+       xfs_iunlock(dp, XFS_IOLOCK_SHARED);
        return 0;
 
 out_free_name:
        if (ci_name)
                kmem_free(ci_name->name);
-out:
+out_unlock:
+       xfs_iunlock(dp, XFS_IOLOCK_SHARED);
        *ipp = NULL;
        return error;
 }
                goto out_trans_cancel;
 
 
-       xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
+       xfs_ilock(dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL |
+                     XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT);
        unlock_dp_on_error = true;
 
        xfs_bmap_init(&free_list, &first_block);
         * the transaction cancel unlocking dp so don't do it explicitly in the
         * error path.
         */
-       xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
        unlock_dp_on_error = false;
 
        error = xfs_dir_createname(tp, dp, name, ip->i_ino,
        xfs_qm_dqrele(pdqp);
 
        if (unlock_dp_on_error)
-               xfs_iunlock(dp, XFS_ILOCK_EXCL);
+               xfs_iunlock(dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
        return error;
 }
 
        if (error)
                goto error_return;
 
+       xfs_ilock(tdp, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT);
        xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL);
 
        xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
-       xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, tdp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
 
        /*
         * If we are using project inheritance, we only allow hard link
                goto out_trans_cancel;
        }
 
+       xfs_ilock(dp, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT);
        xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL);
 
-       xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
        /*
         * whether the target directory is the same as the source
         * directory, we can lock from 2 to 4 inodes.
         */
+       if (!new_parent)
+               xfs_ilock(src_dp, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT);
+       else
+               xfs_lock_two_inodes(src_dp, target_dp,
+                                   XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT);
+
        xfs_lock_inodes(inodes, num_inodes, XFS_ILOCK_EXCL);
 
        /*
         * we can rely on either trans_commit or trans_cancel to unlock
         * them.
         */
-       xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, src_dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
        if (new_parent)
-               xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL);
+               xfs_trans_ijoin(tp, target_dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL);
        if (target_ip)
                xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL);