From patchwork Wed Apr 18 02:50:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 10347293 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 75B2A60365 for ; Wed, 18 Apr 2018 02:50:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 64CA727FA5 for ; Wed, 18 Apr 2018 02:50:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 578842834A; Wed, 18 Apr 2018 02:50:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D2B5328384 for ; Wed, 18 Apr 2018 02:50:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753446AbeDRCum (ORCPT ); Tue, 17 Apr 2018 22:50:42 -0400 Received: from aserp2120.oracle.com ([141.146.126.78]:49320 "EHLO aserp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753144AbeDRCul (ORCPT ); Tue, 17 Apr 2018 22:50:41 -0400 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w3I2kjWK103957; Wed, 18 Apr 2018 02:50:26 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=date : from : to : cc : subject : message-id : mime-version : content-type; s=corp-2017-10-26; bh=v6VNvJD1RWtHecg1NNMGnZSgS596yhDydiVLbTdESTk=; b=gQiZ/PVJZS3IGnsWqxWGK6lBUMT8vqqzpLp/rY8M7d3cKkrHbFsUAOBpuJYaqb+GKcek 6IEn9I9k8r7WJBEd0XAU6vQb2HR/rUPCjrajZAWZp0fWnSFAxazmGGpfEHaVzsYrFeFB N25jLgWaOt9GZlt9569+MBkz6YIx697UCoujEpk21/iwQIm8b0OhOW9iuqMQpqnfqRp3 qdAHKcv9ejZ6Ig1RW6IE7Ovztc0XqSGKUekB/ekpVb2VAvI6FPi4OdlEMyzDWwsLEbml Bm4+Bf1xobp872jTlvtrU1pyJxHyMc/4a61q6AHvSKbOYG8hkWD20gDtTi7wd3lgGEH2 Mg== Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp2120.oracle.com with ESMTP id 2hdrxn8k9v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 18 Apr 2018 02:50:25 +0000 Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.14.4/8.14.4) with ESMTP id w3I2oP4T030316 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 18 Apr 2018 02:50:25 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id w3I2oODD002305; Wed, 18 Apr 2018 02:50:24 GMT Received: from localhost (/10.159.132.124) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 17 Apr 2018 19:50:24 -0700 Date: Tue, 17 Apr 2018 19:50:23 -0700 From: "Darrick J. Wong" To: xfs , linux-fsdevel Cc: Christoph Hellwig , linux-mm@kvack.org Subject: [PATCH] iomap: add a swapfile activation function Message-ID: <20180418025023.GM24738@magnolia> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8866 signatures=668698 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1804180024 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Darrick J. Wong 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 --- 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 */