[Devel] [PATCH RH7 2/3] ext4: Introduce ext4_fastmap()

Kirill Tkhai ktkhai at virtuozzo.com
Wed Jun 17 19:09:30 MSK 2020


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 at virtuozzo.com>
---
 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(+)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f2d849c05cde..193ef8903a36 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 b187b9bbe5fc..2ee774a54ad4 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 c2bc8c7ccfca..a4c1ab7c9a7c 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 4037bf4dd62b..598d7ec03578 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;
 
 




More information about the Devel mailing list