From: Christoph Hellwig <hch@infradead.org>
To: "Darrick J. Wong" <darrick.wong@oracle.com>
Cc: xfs <linux-xfs@vger.kernel.org>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>,
Christoph Hellwig <hch@infradead.org>,
linux-mm@kvack.org
Subject: Re: [PATCH] iomap: add a swapfile activation function
Date: Tue, 24 Apr 2018 10:35:39 -0700 [thread overview]
Message-ID: <20180424173539.GB25233@infradead.org> (raw)
In-Reply-To: <20180418025023.GM24738@magnolia>
This looks much better than using bmap, but I still think that
having the swap code build its own ineffecient extents maps is
a horible idea..
On Tue, Apr 17, 2018 at 07:50:23PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
>
> Add a new iomap_swapfile_activate function so that filesystems can
> activate swap files without having to use the obsolete and slow bmap
> function.
>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
> fs/iomap.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
> fs/xfs/xfs_aops.c | 12 ++++++
> include/linux/iomap.h | 7 +++
> 3 files changed, 118 insertions(+)
>
> diff --git a/fs/iomap.c b/fs/iomap.c
> index afd1635..ace921b 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -1089,3 +1089,102 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
> return ret;
> }
> EXPORT_SYMBOL_GPL(iomap_dio_rw);
> +
> +/* Swapfile activation */
> +
> +struct iomap_swapfile_info {
> + struct swap_info_struct *sis;
> + uint64_t lowest_ppage; /* lowest physical addr seen (pages) */
> + uint64_t highest_ppage; /* highest physical addr seen (pages) */
> + unsigned long expected_page_no; /* next logical offset wanted (pages) */
> + int nr_extents; /* extent count */
> +};
> +
> +static loff_t iomap_swapfile_activate_actor(struct inode *inode, loff_t pos,
> + loff_t count, void *data, struct iomap *iomap)
> +{
> + struct iomap_swapfile_info *isi = data;
> + unsigned long page_no = iomap->offset >> PAGE_SHIFT;
> + unsigned long nr_pages = iomap->length >> PAGE_SHIFT;
> + uint64_t first_ppage = iomap->addr >> PAGE_SHIFT;
> + uint64_t last_ppage = ((iomap->addr + iomap->length) >> PAGE_SHIFT) - 1;
> +
> + /* Only one bdev per swap file. */
> + if (iomap->bdev != isi->sis->bdev)
> + goto err;
> +
> + /* Must be aligned to a page boundary. */
> + if ((iomap->offset & ~PAGE_MASK) || (iomap->addr & ~PAGE_MASK) ||
> + (iomap->length & ~PAGE_MASK))
> + goto err;
> +
> + /* Only real or unwritten extents. */
> + if (iomap->type != IOMAP_MAPPED && iomap->type != IOMAP_UNWRITTEN)
> + goto err;
> +
> + /* No sparse files. */
> + if (isi->expected_page_no != page_no)
> + 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;
> +
> + /*
> + * Calculate how much swap space we're adding; the first page contains
> + * the swap header and doesn't count.
> + */
> + if (page_no == 0)
> + first_ppage++;
> + if (isi->lowest_ppage > first_ppage)
> + isi->lowest_ppage = first_ppage;
> + if (isi->highest_ppage < last_ppage)
> + isi->highest_ppage = last_ppage;
> +
> + /* Add extent, set up for the next call. */
> + isi->nr_extents += add_swap_extent(isi->sis, page_no, nr_pages,
> + first_ppage);
> + isi->expected_page_no = page_no + nr_pages;
> +
> + return count;
> +err:
> + pr_err("swapon: swapfile has holes\n");
> + return -EINVAL;
> +}
> +
> +int iomap_swapfile_activate(struct swap_info_struct *sis,
> + struct file *swap_file, sector_t *pagespan,
> + const struct iomap_ops *ops)
> +{
> + struct iomap_swapfile_info isi = {
> + .sis = sis,
> + .lowest_ppage = (sector_t)-1ULL,
> + };
> + struct address_space *mapping = swap_file->f_mapping;
> + struct inode *inode = mapping->host;
> + loff_t pos = 0;
> + loff_t len = i_size_read(inode);
> + loff_t ret;
> +
> + ret = filemap_write_and_wait(inode->i_mapping);
> + if (ret)
> + return ret;
> +
> + while (len > 0) {
> + ret = iomap_apply(inode, pos, len, IOMAP_REPORT,
> + ops, &isi, iomap_swapfile_activate_actor);
> + if (ret <= 0)
> + return ret;
> +
> + pos += ret;
> + len -= ret;
> + }
> +
> + *pagespan = 1 + isi.highest_ppage - isi.lowest_ppage;
> + sis->max = isi.expected_page_no;
> + sis->pages = isi.expected_page_no - 1;
> + sis->highest_bit = isi.expected_page_no - 1;
> + return isi.nr_extents;
> +}
> +EXPORT_SYMBOL_GPL(iomap_swapfile_activate);
> diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
> index 0ab824f..80de476 100644
> --- a/fs/xfs/xfs_aops.c
> +++ b/fs/xfs/xfs_aops.c
> @@ -1475,6 +1475,16 @@ xfs_vm_set_page_dirty(
> return newly_dirty;
> }
>
> +static int
> +xfs_iomap_swapfile_activate(
> + struct swap_info_struct *sis,
> + struct file *swap_file,
> + sector_t *span)
> +{
> + sis->bdev = xfs_find_bdev_for_inode(file_inode(swap_file));
> + return iomap_swapfile_activate(sis, swap_file, span, &xfs_iomap_ops);
> +}
> +
> const struct address_space_operations xfs_address_space_operations = {
> .readpage = xfs_vm_readpage,
> .readpages = xfs_vm_readpages,
> @@ -1488,6 +1498,7 @@ const struct address_space_operations xfs_address_space_operations = {
> .migratepage = buffer_migrate_page,
> .is_partially_uptodate = block_is_partially_uptodate,
> .error_remove_page = generic_error_remove_page,
> + .swap_activate = xfs_iomap_swapfile_activate,
> };
>
> const struct address_space_operations xfs_dax_aops = {
> @@ -1495,4 +1506,5 @@ const struct address_space_operations xfs_dax_aops = {
> .direct_IO = noop_direct_IO,
> .set_page_dirty = noop_set_page_dirty,
> .invalidatepage = noop_invalidatepage,
> + .swap_activate = xfs_iomap_swapfile_activate,
> };
> diff --git a/include/linux/iomap.h b/include/linux/iomap.h
> index 19a07de..66d1c35 100644
> --- a/include/linux/iomap.h
> +++ b/include/linux/iomap.h
> @@ -106,4 +106,11 @@ 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);
>
> +struct file;
> +struct swap_info_struct;
> +
> +int iomap_swapfile_activate(struct swap_info_struct *sis,
> + struct file *swap_file, sector_t *pagespan,
> + const struct iomap_ops *ops);
> +
> #endif /* LINUX_IOMAP_H */
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
---end quoted text---
next prev parent reply other threads:[~2018-04-24 17:35 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-18 2:50 [PATCH] iomap: add a swapfile activation function Darrick J. Wong
2018-04-21 12:33 ` Jan Kara
2018-05-02 20:29 ` Darrick J. Wong
2018-04-24 17:35 ` Christoph Hellwig [this message]
2018-04-25 23:46 ` Darrick J. Wong
2018-04-26 5:57 ` Christoph Hellwig
2018-04-26 7:27 ` Omar Sandoval
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=20180424173539.GB25233@infradead.org \
--to=hch@infradead.org \
--cc=darrick.wong@oracle.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.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).