linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Matthew Wilcox <willy@infradead.org>
To: hch@infradead.org
Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>,
	linux-xfs@vger.kernel.org
Subject: [PATCH 1/2] iomap: Add iomap_iter API
Date: Wed,  1 Apr 2020 08:25:21 -0700	[thread overview]
Message-ID: <20200401152522.20737-2-willy@infradead.org> (raw)
In-Reply-To: <20200401152522.20737-1-willy@infradead.org>

From: "Matthew Wilcox (Oracle)" <willy@infradead.org>

To replace the apply API

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/iomap/Makefile     |  2 +-
 fs/iomap/iter.c       | 81 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/iomap.h | 24 +++++++++++++
 3 files changed, 106 insertions(+), 1 deletion(-)
 create mode 100644 fs/iomap/iter.c

diff --git a/fs/iomap/Makefile b/fs/iomap/Makefile
index eef2722d93a1..477e5e79f874 100644
--- a/fs/iomap/Makefile
+++ b/fs/iomap/Makefile
@@ -9,7 +9,7 @@ ccflags-y += -I $(srctree)/$(src)		# needed for trace events
 obj-$(CONFIG_FS_IOMAP)		+= iomap.o
 
 iomap-y				+= trace.o \
-				   apply.o \
+				   apply.o iter.o \
 				   buffered-io.o \
 				   direct-io.o \
 				   fiemap.o \
diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c
new file mode 100644
index 000000000000..1d668fdd928e
--- /dev/null
+++ b/fs/iomap/iter.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (c) 2016-2018 Christoph Hellwig.
+ */
+#include <linux/module.h>
+#include <linux/compiler.h>
+#include <linux/fs.h>
+#include <linux/iomap.h>
+#include "trace.h"
+
+/*
+ * Execute a iomap write on a segment of the mapping that spans a
+ * contiguous range of pages that have identical block mapping state.
+ *
+ * This avoids the need to map pages individually, do individual allocations
+ * for each page and most importantly avoid the need for filesystem specific
+ * locking per page. Instead, all the operations are amortised over the entire
+ * range of pages. It is assumed that the filesystems will lock whatever
+ * resources they require in the iomap_begin call, and release them in the
+ * iomap_end call.
+ */
+loff_t iomap_iter(struct iomap_iter *iter, loff_t written)
+{
+	const struct iomap_ops *ops = iter->ops;
+	struct iomap *iomap = &iter->iomap;
+	struct iomap *srcmap = &iter->srcmap;
+	loff_t end, ret = 0;
+
+	trace_iomap_apply(iter->inode, iter->pos, iter->len, iter->flags,
+			iter->ops, NULL, _RET_IP_);
+
+	if (written != IOMAP_FIRST_CALL) {
+		if (ops->iomap_end)
+			ret = ops->iomap_end(iter->inode, iter->pos,
+					iter->len, written > 0 ? written : 0,
+					iter->flags, iomap);
+		if (written < 0)
+			return written;
+		if (ret < 0)
+			return ret;
+		iter->pos += written;
+		iter->len -= written;
+	}
+
+	/*
+	 * Need to map a range from start position for length bytes. This can
+	 * span multiple pages - it is only guaranteed to return a range of a
+	 * single type of pages (e.g. all into a hole, all mapped or all
+	 * unwritten). Failure at this point has nothing to undo.
+	 *
+	 * If allocation is required for this range, reserve the space now so
+	 * that the allocation is guaranteed to succeed later on. Once we copy
+	 * the data into the page cache pages, then we cannot fail otherwise we
+	 * expose transient stale data. If the reserve fails, we can safely
+	 * back out at this point as there is nothing to undo.
+	 */
+	ret = ops->iomap_begin(iter->inode, iter->pos, iter->len,
+			iter->flags, iomap, srcmap);
+	if (ret)
+		return ret;
+	if (WARN_ON(iomap->offset > iter->pos))
+		return -EIO;
+	if (WARN_ON(iomap->offset + iomap->length <= iter->pos))
+		return -EIO;
+	if (WARN_ON(iomap->length == 0))
+		return -EIO;
+
+	trace_iomap_apply_dstmap(iter->inode, iomap);
+	if (srcmap->type != IOMAP_HOLE)
+		trace_iomap_apply_srcmap(iter->inode, srcmap);
+
+	/*
+	 * Cut down the length to the one actually provided by the filesystem,
+	 * as it might not be able to give us the whole size that we requested.
+	 */
+	end = iomap->offset + iomap->length;
+	if (srcmap->type != IOMAP_HOLE)
+		end = min_t(loff_t, end, srcmap->offset + srcmap->length);
+	return min(iter->len, end - iter->pos);
+}
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 8b09463dae0d..ec00a2268f14 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -142,6 +142,30 @@ struct iomap_ops {
 			ssize_t written, unsigned flags, struct iomap *iomap);
 };
 
+struct iomap_iter {
+	struct inode *inode;
+	const struct iomap_ops *ops;
+	loff_t pos;
+	loff_t len;
+	unsigned flags;
+	struct iomap iomap;
+	struct iomap srcmap;
+};
+
+#define DEFINE_IOMAP_ITER(name, _inode, _pos, _len, _flags, _ops)	\
+	struct iomap_iter name = {					\
+		.inode = _inode,					\
+		.ops = _ops,						\
+		.pos = _pos,						\
+		.len = _len,						\
+		.flags = _flags,					\
+	}
+
+/* Magic value for first call to iterator */
+#define IOMAP_FIRST_CALL	LLONG_MIN
+
+loff_t iomap_iter(struct iomap_iter *, loff_t written);
+
 /*
  * Main iomap iterator function.
  */
-- 
2.25.1


  reply	other threads:[~2020-04-01 15:25 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-01 15:25 [RFC 0/2] Begin switching iomap from apply to iter Matthew Wilcox
2020-04-01 15:25 ` Matthew Wilcox [this message]
2020-04-01 15:42   ` [PATCH 1/2] iomap: Add iomap_iter API Christoph Hellwig
2020-04-01 18:42     ` Matthew Wilcox
2020-04-22 15:19       ` Jan Kara
2020-04-01 19:20     ` Matthew Wilcox
2020-04-02  7:48       ` Christoph Hellwig
2020-04-01 15:25 ` [PATCH 2/2] iomap: Convert page_mkwrite to iter API Matthew Wilcox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200401152522.20737-2-willy@infradead.org \
    --to=willy@infradead.org \
    --cc=hch@infradead.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).