}
 
 static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend,
-                             struct extent_state **cached_state, bool writing)
+                             struct extent_state **cached_state,
+                             unsigned int iomap_flags)
 {
+       const bool writing = (iomap_flags & IOMAP_WRITE);
+       const bool nowait = (iomap_flags & IOMAP_NOWAIT);
+       struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        struct btrfs_ordered_extent *ordered;
        int ret = 0;
 
        while (1) {
-               lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend,
-                                cached_state);
+               if (nowait) {
+                       if (!try_lock_extent(io_tree, lockstart, lockend))
+                               return -EAGAIN;
+               } else {
+                       lock_extent_bits(io_tree, lockstart, lockend, cached_state);
+               }
                /*
                 * We're concerned with the entire range that we're going to be
                 * doing DIO to, so we need to make sure there's no ordered
                                                         lockstart, lockend)))
                        break;
 
-               unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
-                                    cached_state);
+               unlock_extent_cached(io_tree, lockstart, lockend, cached_state);
 
                if (ordered) {
+                       if (nowait) {
+                               btrfs_put_ordered_extent(ordered);
+                               ret = -EAGAIN;
+                               break;
+                       }
                        /*
                         * If we are doing a DIO read and the ordered extent we
                         * found is for a buffered write, we can not wait for it
                            test_bit(BTRFS_ORDERED_DIRECT, &ordered->flags))
                                btrfs_start_ordered_extent(ordered, 1);
                        else
-                               ret = -ENOTBLK;
+                               ret = nowait ? -EAGAIN : -ENOTBLK;
                        btrfs_put_ordered_extent(ordered);
                } else {
                        /*
                         * ordered extent to complete while holding a lock on
                         * that page.
                         */
-                       ret = -ENOTBLK;
+                       ret = nowait ? -EAGAIN : -ENOTBLK;
                }
 
                if (ret)
 
        /*
         * If this errors out it's because we couldn't invalidate pagecache for
-        * this range and we need to fallback to buffered.
+        * this range and we need to fallback to buffered IO, or we are doing a
+        * NOWAIT read/write and we need to block.
         */
-       if (lock_extent_direct(inode, lockstart, lockend, &cached_state, write)) {
-               ret = -ENOTBLK;
+       ret = lock_extent_direct(inode, lockstart, lockend, &cached_state, flags);
+       if (ret < 0)
                goto err;
-       }
 
        em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, start, len);
        if (IS_ERR(em)) {