linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Aleksei Besogonov <cyberax@amazon.com>
To: <linux-xfs@vger.kernel.org>, <linux-fsdevel@vger.kernel.org>,
	<darrick.wong@oracle.com>
Cc: Aleksei Besogonov <cyberax@amazon.com>
Subject: [PATCH 1/2] fs: Add iomap_swap_activate
Date: Tue, 1 May 2018 18:48:06 +0000	[thread overview]
Message-ID: <20180501184807.123111-2-cyberax@amazon.com> (raw)
In-Reply-To: <20180501184807.123111-1-cyberax@amazon.com>

This commit adds an alternative to generic_swapfile_activate function
based on iomap family. The major driver for this is swap file support
on XFS, currently it doesn't work on files with holes due to deficiencies
in the old bmap() interface that is used by generic_swapfile_activate.
---
 fs/iomap.c            | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/iomap.h |   5 +++
 mm/swapfile.c         |   1 +
 3 files changed, 112 insertions(+)

diff --git a/fs/iomap.c b/fs/iomap.c
index afd163586aa0..8ac6dcbfbeb6 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -94,6 +94,7 @@ iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags,
 
 	return written ? written : ret;
 }
+EXPORT_SYMBOL_GPL(iomap_apply);
 
 static void
 iomap_write_failed(struct inode *inode, loff_t pos, unsigned len)
@@ -1089,3 +1090,108 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 	return ret;
 }
 EXPORT_SYMBOL_GPL(iomap_dio_rw);
+
+struct iomap_swap_walker_context
+{
+    struct swap_info_struct *sis;
+    unsigned int page_no;
+    unsigned int nr_extents;
+    sector_t *span;
+};
+
+static loff_t iomap_swap_map(struct inode *inode, loff_t pos, loff_t length,
+			     void *data, struct iomap *iomap)
+{
+	struct iomap_swap_walker_context *ctx = data;
+	unsigned int blocks_per_page = PAGE_SIZE >> inode->i_blkbits;
+	u64 num_pages;
+	u64 aligned_address;
+	sector_t disk_pos;
+	loff_t eff_length;
+	loff_t ret;
+
+	/* Validate the extent */
+
+	/* Only one bdev per swap file. */
+	if (iomap->bdev != ctx->sis->bdev)
+		goto err;
+	/* Only real or unwritten extents. */
+	if (iomap->type != IOMAP_MAPPED && iomap->type != IOMAP_UNWRITTEN)
+		goto err;
+	/* No uncommitted metadata or shared blocks or inline data. */
+	if (iomap->flags & (IOMAP_F_DIRTY | IOMAP_F_SHARED | IOMAP_F_DATA_INLINE))
+		goto err;
+
+	/*
+	 * Swap extents need to be PAGE_SIZE aligned on the disk
+	 */
+	aligned_address = ALIGN(iomap->addr, PAGE_SIZE);
+	eff_length = length - (aligned_address - iomap->addr);
+	BUG_ON(eff_length > length);
+	disk_pos = aligned_address >> inode->i_blkbits;
+
+	if (eff_length < 0)
+		return length; /* Continue probing */
+
+	num_pages = eff_length / PAGE_SIZE;
+
+	/* Can't add blocks less than 1 page */
+	if (num_pages == 0)
+		return length; /* Continue probing */
+
+	ret = add_swap_extent(ctx->sis, ctx->page_no, num_pages, disk_pos);
+	if (ret < 0)
+		return ret;
+
+	ctx->nr_extents += ret;
+	ctx->page_no += num_pages;
+	(*ctx->span) += num_pages * blocks_per_page;
+
+	return length; /* continue probing */
+err:
+	pr_err("swapon: swapfile has holes\n");
+	return -EINVAL;
+}
+
+int iomap_swap_activate(struct swap_info_struct *sis, struct file *file,
+			sector_t *span, const struct iomap_ops *ops)
+{
+	struct iomap_swap_walker_context ctx = {
+		.sis = sis,
+		.page_no = 0,
+		.nr_extents = 0,
+		.span = span
+	};
+
+	struct inode * inode = file_inode(file);
+	loff_t len = i_size_read(inode);
+	loff_t pos = 0;
+	loff_t ret = -EINVAL;
+
+
+	ret = filemap_write_and_wait(inode->i_mapping);
+	if (ret)
+		return ret;
+
+	while(len > 0) {
+		ret = iomap_apply(inode, pos, len, IOMAP_REPORT, ops,
+				  &ctx, iomap_swap_map);
+		if (ret <= 0)
+			break;
+
+		pos += ret;
+		len -= ret;
+	}
+
+	if (ret < 0) {
+		pr_err("Failed to activate the swap file\n");
+		return -EINVAL;
+	}
+
+	sis->max = ctx.page_no == 0 ? 1 : ctx.page_no;
+	sis->pages = ctx.page_no;
+	sis->highest_bit = ctx.page_no;
+
+	return ctx.nr_extents;
+}
+EXPORT_SYMBOL_GPL(iomap_swap_activate);
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 19a07de28212..a85da0db6c2e 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -10,6 +10,8 @@ struct iov_iter;
 struct kiocb;
 struct vm_area_struct;
 struct vm_fault;
+struct file;
+struct swap_info_struct;
 
 /*
  * Types of block ranges for iomap mappings:
@@ -106,4 +108,7 @@ typedef int (iomap_dio_end_io_t)(struct kiocb *iocb, ssize_t ret,
 ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 		const struct iomap_ops *ops, iomap_dio_end_io_t end_io);
 
+int iomap_swap_activate(struct swap_info_struct *sis, struct file *file,
+			sector_t *span, const struct iomap_ops *ops);
+
 #endif /* LINUX_IOMAP_H */
diff --git a/mm/swapfile.c b/mm/swapfile.c
index c7a33717d079..9e6d3c1a882e 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2381,6 +2381,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
 	list_add_tail(&new_se->list, &sis->first_swap_extent.list);
 	return 1;
 }
+EXPORT_SYMBOL_GPL(add_swap_extent);
 
 /*
  * A `swap extent' is a simple thing which maps a contiguous range of pages
-- 
2.14.1

  reply	other threads:[~2018-05-01 18:48 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-01 18:48 [PATCH 0/2] RFC: iomap-based swapfile activation Aleksei Besogonov
2018-05-01 18:48 ` Aleksei Besogonov [this message]
2018-05-01 20:44   ` [PATCH 1/2] fs: Add iomap_swap_activate kbuild test robot
2018-05-02  1:02   ` kbuild test robot
2018-05-01 18:48 ` [PATCH 2/2] xfs: add support for iomap-based swapfile activation Aleksei Besogonov
2018-05-01 19:16 ` [PATCH 0/2] RFC: " Eric Sandeen
  -- strict thread matches above, loose matches on Subject: below --
2018-04-20 22:08 [PATCH 0/2] RFC: iomap-based swap file activation Aleksei Besogonov
2018-04-20 22:08 ` [PATCH 1/2] fs: Add iomap_swap_activate Aleksei Besogonov
2018-04-25 21:34   ` kbuild test robot
2018-04-25 21:38   ` kbuild test robot

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=20180501184807.123111-2-cyberax@amazon.com \
    --to=cyberax@amazon.com \
    --cc=darrick.wong@oracle.com \
    --cc=linux-fsdevel@vger.kernel.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).