From patchwork Wed May 2 20:32:28 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: 10376433 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 24C6E6038F for ; Wed, 2 May 2018 20:32:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0F85228EAB for ; Wed, 2 May 2018 20:32:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 01F7D28EB5; Wed, 2 May 2018 20:32: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=-3.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C16E28EAB for ; Wed, 2 May 2018 20:32:53 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id BF2996B0011; Wed, 2 May 2018 16:32:52 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id BA1786B0012; Wed, 2 May 2018 16:32:52 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A6AA86B0022; Wed, 2 May 2018 16:32:52 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-wm0-f72.google.com (mail-wm0-f72.google.com [74.125.82.72]) by kanga.kvack.org (Postfix) with ESMTP id 45F856B0011 for ; Wed, 2 May 2018 16:32:52 -0400 (EDT) Received: by mail-wm0-f72.google.com with SMTP id z76so8431096wmh.9 for ; Wed, 02 May 2018 13:32:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:dkim-signature:date:from:to:cc:subject :message-id:mime-version:content-disposition:user-agent; bh=FH6IqyHbU86SVnI0EJcK4rFiv+RUnQT/dOnL2pYSv0I=; b=JmB4+rSPhr5uCJ0D36cKiLzX+FJZMYQRc7lYWVLx9d2m6VyWVS3hNkIMODuoL9ZXCC vCSjuXqkwImWjareLW0d3PBr1mZXk11JDv1Vzr6IvOxcMhTQ7hO4x6Lk+GcVjTZnq99k FJKdQYMWOfpDulzZeKC0Ha2bAF2mWGoRrczAwwAY1RiAnTxNwqr+RdxV9p1CO3Vftrqo tyO2zYmlV5ia0+Yxr6fkQHfhPBEcqxtyHDLQtZePTe7S8y51GdLh0rSyssQ818vdNWcA kPhhqct4/EHETl/ELE+snEeiP/pJiR+ELNj9zSMqq/LnxEuVfQ7Mfyw1G9ieNxinOY8n iE2Q== X-Gm-Message-State: ALQs6tD8ROzWcklWQBXfXNhGXyF6+1jSWPp/4DMOvYxIux4Me/SZbfNo zGywkdHSbFcqRkIEUtqCGjiTRcBErh4/V8S7UQsvINOo1BYex3wGWxmoBSGwVUQ7zh28fO1TBR8 A/rGgOPJvm/yXupDwTBtrQsEyAi+T8i2CBtybOlCqTbgbjYUTcfARXNNhA4Nna5jyuQ== X-Received: by 2002:a50:d70d:: with SMTP id t13-v6mr11861315edi.260.1525293171796; Wed, 02 May 2018 13:32:51 -0700 (PDT) X-Google-Smtp-Source: AB8JxZoKowhiNFADXC/cPuLdGBLV5vGtnHLvIjn689HAliWL1Ad10yHsu2a9s8Mb76K3EsR9ZoZq X-Received: by 2002:a50:d70d:: with SMTP id t13-v6mr11861264edi.260.1525293170894; Wed, 02 May 2018 13:32:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525293170; cv=none; d=google.com; s=arc-20160816; b=SpSXs+S36it/V9t3fJHipSYRBlj8bP8p3R5bueKw2BhmEcT+3TWL1DpFYO+DCL/zPq x9s1E3BJOo1+x9hRhj0mr/wpEQxZ9qqnG5G06wqRqBYz1MUK+sKg4/8Tw6qqaxyHvna8 yCc8pgIzali/r8DWdiWuFEzXHqiP2SBD2uIy7nPueBPXa//+0AtzYIRHWqJkbM/f3kSe 0tl9ArXi9FbEzYhJIvxYqHdUUVYs8fKr4eONUXieBBHa8FWUD9Tf0cvpu4nlZ9MsPSCE GfhuAjBW6D96luJjYILsJkOLaBVwc16u+/NiEU2PdgK6yz85lp0yxLJTvD0pFTCTm0hl qdJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=user-agent:content-disposition:mime-version:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=FH6IqyHbU86SVnI0EJcK4rFiv+RUnQT/dOnL2pYSv0I=; b=ld7N2Vxc+fV//uHTb7i1tHNDQ0hfBgaBam8Bubmb+UookX80UUYL532BRPwMmpzKFo SanznLWVw1j/1AKQgpVXSm2QkAsj9Xe83mSndstQJ81lPD5LotM8vPY52nJWCkWc54ar 8T4ypBeaPGTMpJBVrLNrQfg4bim3ckMfu/DkThHr6/CnvKbmKR3xl8tu5jBkxMEAyeSE 4XHEqkQIQKM6uPljnTES/1LQFIvXKti0Jvjv8k7oFRoskVNYlmQSHV0GxgQ0x17FNPr0 k5hTIsGquy9GhGchz3dRL17ScUW0o5y/X+7yFdb8aIIAqt9EiayW2IT2wfzi92OO/7n2 9V/Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@oracle.com header.s=corp-2017-10-26 header.b=XdELsD4d; spf=pass (google.com: domain of darrick.wong@oracle.com designates 141.146.126.79 as permitted sender) smtp.mailfrom=darrick.wong@oracle.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: from aserp2130.oracle.com (aserp2130.oracle.com. [141.146.126.79]) by mx.google.com with ESMTPS id h3-v6si1364373edn.439.2018.05.02.13.32.50 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 May 2018 13:32:50 -0700 (PDT) Received-SPF: pass (google.com: domain of darrick.wong@oracle.com designates 141.146.126.79 as permitted sender) client-ip=141.146.126.79; Authentication-Results: mx.google.com; dkim=pass header.i=@oracle.com header.s=corp-2017-10-26 header.b=XdELsD4d; spf=pass (google.com: domain of darrick.wong@oracle.com designates 141.146.126.79 as permitted sender) smtp.mailfrom=darrick.wong@oracle.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: from pps.filterd (aserp2130.oracle.com [127.0.0.1]) by aserp2130.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w42KVLgo086672; Wed, 2 May 2018 20:32:31 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=FH6IqyHbU86SVnI0EJcK4rFiv+RUnQT/dOnL2pYSv0I=; b=XdELsD4dhPdhM97OIZ7Fcst3jROvASHNQ8Wer+6LqFGkYQm7n/i8g4tmFHa76MhT1r6C pztozCo4kjP0Dop3XO+6pYLdYtL1m70Dn/mIUwVgIMTQusjTBK5VTbzxBjYLcm0aEIqi Fp2tRQ6zcjbjlqHX+5hSA+oqjHjLxPN0A6q05txvj+pCQQ6UL317BD0iBA8H14Vimluv z/U5vBbxCgrtM/OXNAgshaGOsbtGvP/QHcZ6KCrjeLMIl8yMUUXm4fjDgFbx56HaZfVZ NiuNSodQH96pJy387bRLSpyOZNld5h+K72JlAfY9887S7La7pa2tMnpI38TcgIkHqHty 8Q== Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp2130.oracle.com with ESMTP id 2hmeg5y1ks-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 02 May 2018 20:32:31 +0000 Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.14.4/8.14.4) with ESMTP id w42KWVn5021762 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 2 May 2018 20:32:31 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id w42KWU3F015198; Wed, 2 May 2018 20:32:30 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 02 May 2018 13:32:29 -0700 Date: Wed, 2 May 2018 13:32:28 -0700 From: "Darrick J. Wong" To: xfs , linux-fsdevel , linux-mm@kvack.org, darrick.wong@oracle.com Cc: hch@infradead.org, cyberax@amazon.com, jack@suse.cz, osandov@osandov.com, Eryu Guan Subject: [PATCH 1/2] iomap: add a swapfile activation function Message-ID: <20180502203228.GA4141@magnolia> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.4 (2018-02-28) X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=8881 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-1805020172 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Add a new iomap_swapfile_activate function so that filesystems can activate swap files without having to use the obsolete and slow bmap function. This also enables XFS to support having swap files with unwritten extens and swap files on the realtime device. Signed-off-by: Darrick J. Wong --- v2: document the swap file layout requirements, combine adjacent real/unwritten extents, align reported swap extents to physical page size boundaries, fix compiler errors when swap disabled --- fs/iomap.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_aops.c | 12 ++++ include/linux/iomap.h | 11 +++ 3 files changed, 181 insertions(+) diff --git a/fs/iomap.c b/fs/iomap.c index afd163586aa0..36b0caff7028 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "internal.h" @@ -1089,3 +1090,160 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, return ret; } EXPORT_SYMBOL_GPL(iomap_dio_rw); + +/* Swapfile activation */ + +#ifdef CONFIG_SWAP +struct iomap_swapfile_info { + struct iomap iomap; /* accumulated iomap */ + 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 nr_pages; /* number of pages collected */ + int nr_extents; /* extent count */ +}; + +/* + * Collect physical extents for this swap file. Physical extents reported to + * the swap code must be trimmed to align to a page boundary. The logical + * offset within the file is irrelevant since the swapfile code maps logical + * page numbers of the swap device to the physical page-aligned extents. + */ +static int iomap_swapfile_add_extent(struct iomap_swapfile_info *isi) +{ + struct iomap *iomap = &isi->iomap; + unsigned long nr_pages; + uint64_t first_ppage; + uint64_t first_ppage_reported; + uint64_t last_ppage; + int error; + + /* + * Round the start up and the length down so that the physical + * extent aligns to a page boundary. + */ + first_ppage = ALIGN(iomap->addr, PAGE_SIZE) >> PAGE_SHIFT; + last_ppage = (ALIGN_DOWN(iomap->addr + iomap->length, PAGE_SIZE) >> + PAGE_SHIFT) - 1; + nr_pages = last_ppage - first_ppage + 1; + + /* Skip zero-length page-aligned extents and holes. */ + if (nr_pages == 0) + return 0; + + /* + * Calculate how much swap space we're adding; the first page contains + * the swap header and doesn't count. The mm still wants that first + * page fed to add_swap_extent, however. + */ + first_ppage_reported = first_ppage; + if (iomap->offset == 0) + first_ppage_reported++; + if (isi->lowest_ppage > first_ppage_reported) + isi->lowest_ppage = first_ppage_reported; + if (isi->highest_ppage < last_ppage) + isi->highest_ppage = last_ppage; + + /* Add extent, set up for the next call. */ + error = add_swap_extent(isi->sis, isi->nr_pages, nr_pages, first_ppage); + if (error < 0) + return error; + isi->nr_extents += error; + isi->nr_pages += nr_pages; + return 0; +} + +/* + * Accumulate iomaps for this swap file. We have to accumulate iomaps because + * swap only cares about contiguous page-aligned physical extents and makes no + * distinction between written and unwritten extents. + */ +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; + int error; + + /* Skip holes. */ + if (iomap->type == IOMAP_HOLE) + goto out; + + /* Only one bdev per swap file. */ + if (iomap->bdev != isi->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; + + if (isi->iomap.length == 0) { + /* No accumulated extent, so just store it. */ + memcpy(&isi->iomap, iomap, sizeof(isi->iomap)); + } else if (isi->iomap.addr + isi->iomap.length == iomap->addr) { + /* Append this to the accumulated extent. */ + isi->iomap.length += iomap->length; + } else { + /* Otherwise, add the retained iomap and store this one. */ + error = iomap_swapfile_add_extent(isi); + if (error) + return error; + memcpy(&isi->iomap, iomap, sizeof(isi->iomap)); + } +out: + return count; +err: + pr_err("swapon: file cannot be used for swap\n"); + return -EINVAL; +} + +/* + * Iterate a swap file's iomaps to construct physical extents that can be + * passed to the swapfile subsystem. + */ +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 = ALIGN_DOWN(i_size_read(inode), PAGE_SIZE); + 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; + } + + if (isi.iomap.length) { + ret = iomap_swapfile_add_extent(&isi); + if (ret) + return ret; + } + + *pagespan = 1 + isi.highest_ppage - isi.lowest_ppage; + sis->max = isi.nr_pages; + sis->pages = isi.nr_pages - 1; + sis->highest_bit = isi.nr_pages - 1; + return isi.nr_extents; +} +EXPORT_SYMBOL_GPL(iomap_swapfile_activate); +#endif /* CONFIG_SWAP */ diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 0ab824f574ed..80de476cecf8 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 19a07de28212..7296d474183d 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -106,4 +106,15 @@ 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); +#ifdef CONFIG_SWAP +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); +#else +# define iomap_swapfile_activate (-EIO) +#endif /* CONFIG_SWAP */ + #endif /* LINUX_IOMAP_H */