[RHEL7,COMMIT] ext4: Introduce ext4_fastmap()

Submitted by Konstantin Khorenko on June 18, 2020, 5:09 p.m.

Details

Message ID 202006181709.05IH9DnW002627@finist-ce7.sw.ru
State New
Series "ploop: Add direct queuing support for io_kaio"
Headers show

Commit Message

Konstantin Khorenko June 18, 2020, 5:09 p.m.
The commit is pushed to "branch-rh7-3.10.0-1127.10.1.vz7.162.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1127.10.1.vz7.162.4
------>
commit d9b2b861188547def549d0c90eeb1489c1945eed
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Thu Jun 18 20:09:13 2020 +0300

    ext4: Introduce ext4_fastmap()
    
    This introduces a new function, which is rather similar to ext4_overwrite_io()
    except:
            1)new flag EXT4_GET_BLOCKS_EXTENT_TREE_ONLY is passed;
              it says we're interested in cached extents in extent
              tree, and we don't want initiate any IO to get extent;
            2)ext4_unaligned_aio() check is added, which is one of
              the check we have on direct IO path (ext4_file_write_iter).
    
    The function is supposed to be used as replacement in ploop's extent tree from
    io_direct.c on fastpath, and for the introduction fastpath for io_kaio.c.
    
    Note: in case of io_direct.c it looks strange to have duplicate extent tree
    in io_direct_map.c: 1)io_direct is for ext4 only; 2)ext4 already caches
    extents in rbtree.
    
    Next patch introduces fastpath for io_kaio, but io_direct.c should be converted
    to use ext4 extent tree in the future too.
    
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
    
    =====================
    Patchset description:
    ploop: Add direct queuing support for io_kaio
    
    This introduces a possibility to dispath incomming request directly
    from ploop_make_request() without waking ploop thread up. We queue
    bio in case of it fits in a single extent (like fastpath for io_direct).
    To get the target bio location, ext4 extent tree is used.
    
    Currently, some sanity checks are missed, so that makes ploop file
    unsafe for touching by side software (like we have in io_direct).
    But this patchset is mostly for a view of testing improvements,
    and one else will go on top of this.
    
    Kirill Tkhai (3):
          ext4: Extract logic from ext4_overwrite_io() to underlining function
          ext4: Introduce ext4_fastmap()
          ploop: Introduce fastpath for io_kaio
---
 fs/ext4/ext4.h     |  3 +++
 fs/ext4/file.c     | 21 +++++++++++++++++++++
 fs/ext4/inode.c    |  3 +++
 include/linux/fs.h |  1 +
 4 files changed, 28 insertions(+)

Patch hide | download patch | download mbox

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f2d849c05cdea..193ef8903a36e 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -578,6 +578,9 @@  enum {
 	 * allows jbd2 to avoid submitting data before commit. */
 #define EXT4_GET_BLOCKS_IO_SUBMIT		0x0400
 
+	/* Search in extent tree only */
+#define EXT4_GET_BLOCKS_EXTENT_TREE_ONLY	0x8000
+
 /*
  * The bit position of these flags must not overlap with any of the
  * EXT4_GET_BLOCKS_*.  They are used by ext4_ext_find_extent(),
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index b187b9bbe5fc2..2ee774a54ad4b 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -125,6 +125,26 @@  static bool ext4_overwrite_io(struct inode *inode, loff_t pos, loff_t len)
 	return __ext4_overwrite_io(inode, pos, len, &map, 0);
 }
 
+static int ext4_fastmap(struct inode *inode, sector_t lblk_sec,
+			unsigned int len, sector_t *pblk_sec)
+{
+	struct ext4_map_blocks map;
+	loff_t pos = lblk_sec << 9;
+	bool unaligned_aio, found;
+
+	unaligned_aio = ext4_unaligned_aio(inode, len, pos);
+	if (unaligned_aio)
+		return -ENOENT;
+
+	found = __ext4_overwrite_io(inode, lblk_sec << 9, len, &map,
+				    EXT4_GET_BLOCKS_EXTENT_TREE_ONLY);
+	if (!found)
+		return -ENOENT;
+
+	*pblk_sec = map.m_pblk << (inode->i_blkbits - 9);
+	return 0;
+}
+
 static ssize_t ext4_write_checks(struct kiocb *iocb, struct iov_iter *iter, loff_t *pos)
 {
 	struct file *file = iocb->ki_filp;
@@ -605,5 +625,6 @@  const struct inode_operations ext4_file_inode_operations = {
 	.removexattr	= generic_removexattr,
 	.get_acl	= ext4_get_acl,
 	.fiemap		= ext4_fiemap,
+	.fastmap	= ext4_fastmap,
 };
 
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c2bc8c7ccfca4..a4c1ab7c9a7c6 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -524,6 +524,9 @@  int ext4_map_blocks(handle_t *handle, struct inode *inode,
 		goto found;
 	}
 
+	if (flags & EXT4_GET_BLOCKS_EXTENT_TREE_ONLY)
+		return -ENOENT;
+
 	/*
 	 * Try to see if we can get the block without requesting a new
 	 * file system block.
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4037bf4dd62b0..598d7ec03578f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2013,6 +2013,7 @@  struct inode_operations {
 	int (*atomic_open)(struct inode *, struct dentry *,
 			   struct file *, unsigned open_flag,
 			   umode_t create_mode, int *opened);
+	int (*fastmap)(struct inode *, sector_t, unsigned int, sector_t *);
 } ____cacheline_aligned;