From patchwork Fri Aug 31 22:36:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Sandoval X-Patchwork-Id: 10584517 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C9805112B for ; Fri, 31 Aug 2018 22:36:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BDED22BB98 for ; Fri, 31 Aug 2018 22:36:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B210C2C6A8; Fri, 31 Aug 2018 22:36:51 +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.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 280B82C62F for ; Fri, 31 Aug 2018 22:36:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727466AbeIACqY (ORCPT ); Fri, 31 Aug 2018 22:46:24 -0400 Received: from mail-pf1-f194.google.com ([209.85.210.194]:33679 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727212AbeIACqX (ORCPT ); Fri, 31 Aug 2018 22:46:23 -0400 Received: by mail-pf1-f194.google.com with SMTP id d4-v6so6141287pfn.0 for ; Fri, 31 Aug 2018 15:36:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=T4zypnAVQJfVK6JjN6ITEGJDUN7vtLnMURc1S60reio=; b=VRdbDC8RwDZpz5uRyFK86k/BqH9HXKBFhSOQstZ8fAsztVh6zJVxedfC+6KN5PUgaQ F/0YO+dQNCo+RTCEPsP8yR26BSFUOzwNdP7ZZ4vZd7ciUJENOzx6epK/wx/fvlb3g2M7 ZdDky2cdeELRR/3GKvjdqym/Uqmfo1DjD83GXDQnCnbn7AbDdmiUcWBVbMjrSwQ8+sg9 n/NrL4O8vRyZaAMW68jOdcUguIyc/1jVPqNrRY54EF3x5q2YUcYmc4gyH85XWEpuXxN1 EJNsjQ+Yc/6+8U9Vv4d69t8Sd4mM3YbQb6KqrM8CuDBM9eGM75JcqZKm1eJ+ac+XZFbA 8+nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=T4zypnAVQJfVK6JjN6ITEGJDUN7vtLnMURc1S60reio=; b=Xp1XSe0JYpbVe4ABTyqIVH/NFUjnTC+9lRDVpPuHt+3XEbf/yV6jtcKT8xOoU0r2YE 2zFr1AR3AeRdguGFV1bMPN0/I4XaOsst20PCl223U4coKQG6/Nw0qK/bSRKQMPSmy4PP lO3YHCt3WgOfNpATzEt+zeGeqNA/+ZvpO2aaWCJYnjtaRdM/35ZKIvMZhG0B7nqZVZmq ins8B6VZ7JrVUDyAO/LYjn0PwxVVMYpHlXtkfD1AUgo+M/SNTKgDZI1kpM1sfYaa3E48 QjLlLqEe14KsUchcRezsbNREztWRxPuRkpum5HL5DnZC1Hpo3KbLSY77MeEWAaLaGcUm nPvg== X-Gm-Message-State: APzg51AtHlTYE5YgGFDVAc8xGsQEfw09QY+Aqv7XUSvzIGWlRc0E2af8 zAgf4qKqW9EJVtcIPqb4tpibgKEctRA= X-Google-Smtp-Source: ANB0VdbPD70gTnxv2O5piL4ZfPj6J7i+RSJdLEedOi3aKOx/fe2Ybn4ZY4DOKbQ/gqzDGOfxrskKuw== X-Received: by 2002:a62:5d89:: with SMTP id n9-v6mr18197419pfj.102.1535755008107; Fri, 31 Aug 2018 15:36:48 -0700 (PDT) Received: from vader.thefacebook.com ([2620:10d:c090:200::4:9733]) by smtp.gmail.com with ESMTPSA id r19-v6sm43427403pgo.43.2018.08.31.15.36.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 Aug 2018 15:36:47 -0700 (PDT) From: Omar Sandoval To: linux-btrfs@vger.kernel.org Cc: kernel-team@fb.com Subject: [PATCH v5 1/6] mm: split SWP_FILE into SWP_ACTIVATED and SWP_FS Date: Fri, 31 Aug 2018 15:36:36 -0700 Message-Id: <8c5836f6de55eaca0a1ba0f024598a3a0a3904dc.1535754957.git.osandov@fb.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: References: Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Omar Sandoval The SWP_FILE flag serves two purposes: to make swap_{read,write}page() go through the filesystem, and to make swapoff() call ->swap_deactivate(). For Btrfs, we want the latter but not the former, so split this flag into two. This makes us always call ->swap_deactivate() if ->swap_activate() succeeded, not just if it didn't add any swap extents itself. This also resolves the issue of the very misleading name of SWP_FILE, which is only used for swap files over NFS. Reviewed-by: Nikolay Borisov Signed-off-by: Omar Sandoval --- include/linux/swap.h | 13 +++++++------ mm/page_io.c | 6 +++--- mm/swapfile.c | 13 ++++++++----- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 8e2c11e692ba..0fda0aa743f0 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -167,13 +167,14 @@ enum { SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */ SWP_CONTINUED = (1 << 5), /* swap_map has count continuation */ SWP_BLKDEV = (1 << 6), /* its a block device */ - SWP_FILE = (1 << 7), /* set after swap_activate success */ - SWP_AREA_DISCARD = (1 << 8), /* single-time swap area discards */ - SWP_PAGE_DISCARD = (1 << 9), /* freed swap page-cluster discards */ - SWP_STABLE_WRITES = (1 << 10), /* no overwrite PG_writeback pages */ - SWP_SYNCHRONOUS_IO = (1 << 11), /* synchronous IO is efficient */ + SWP_ACTIVATED = (1 << 7), /* set after swap_activate success */ + SWP_FS = (1 << 8), /* swap file goes through fs */ + SWP_AREA_DISCARD = (1 << 9), /* single-time swap area discards */ + SWP_PAGE_DISCARD = (1 << 10), /* freed swap page-cluster discards */ + SWP_STABLE_WRITES = (1 << 11), /* no overwrite PG_writeback pages */ + SWP_SYNCHRONOUS_IO = (1 << 12), /* synchronous IO is efficient */ /* add others here before... */ - SWP_SCANNING = (1 << 12), /* refcount in scan_swap_map */ + SWP_SCANNING = (1 << 13), /* refcount in scan_swap_map */ }; #define SWAP_CLUSTER_MAX 32UL diff --git a/mm/page_io.c b/mm/page_io.c index aafd19ec1db4..e8653c368069 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -283,7 +283,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, struct swap_info_struct *sis = page_swap_info(page); VM_BUG_ON_PAGE(!PageSwapCache(page), page); - if (sis->flags & SWP_FILE) { + if (sis->flags & SWP_FS) { struct kiocb kiocb; struct file *swap_file = sis->swap_file; struct address_space *mapping = swap_file->f_mapping; @@ -365,7 +365,7 @@ int swap_readpage(struct page *page, bool synchronous) goto out; } - if (sis->flags & SWP_FILE) { + if (sis->flags & SWP_FS) { struct file *swap_file = sis->swap_file; struct address_space *mapping = swap_file->f_mapping; @@ -423,7 +423,7 @@ int swap_set_page_dirty(struct page *page) { struct swap_info_struct *sis = page_swap_info(page); - if (sis->flags & SWP_FILE) { + if (sis->flags & SWP_FS) { struct address_space *mapping = sis->swap_file->f_mapping; VM_BUG_ON_PAGE(!PageSwapCache(page), page); diff --git a/mm/swapfile.c b/mm/swapfile.c index d954b71c4f9c..d3f95833d12e 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -989,7 +989,7 @@ int get_swap_pages(int n_goal, swp_entry_t swp_entries[], int entry_size) goto nextsi; } if (size == SWAPFILE_CLUSTER) { - if (!(si->flags & SWP_FILE)) + if (!(si->flags & SWP_FS)) n_ret = swap_alloc_cluster(si, swp_entries); } else n_ret = scan_swap_map_slots(si, SWAP_HAS_CACHE, @@ -2310,12 +2310,13 @@ static void destroy_swap_extents(struct swap_info_struct *sis) kfree(se); } - if (sis->flags & SWP_FILE) { + if (sis->flags & SWP_ACTIVATED) { struct file *swap_file = sis->swap_file; struct address_space *mapping = swap_file->f_mapping; - sis->flags &= ~SWP_FILE; - mapping->a_ops->swap_deactivate(swap_file); + sis->flags &= ~SWP_ACTIVATED; + if (mapping->a_ops->swap_deactivate) + mapping->a_ops->swap_deactivate(swap_file); } } @@ -2411,8 +2412,10 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) if (mapping->a_ops->swap_activate) { ret = mapping->a_ops->swap_activate(sis, swap_file, span); + if (ret >= 0) + sis->flags |= SWP_ACTIVATED; if (!ret) { - sis->flags |= SWP_FILE; + sis->flags |= SWP_FS; ret = add_swap_extent(sis, 0, sis->max, 0); *span = sis->pages; } From patchwork Fri Aug 31 22:36:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Sandoval X-Patchwork-Id: 10584519 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 768BE174A for ; Fri, 31 Aug 2018 22:36:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6AF722BB98 for ; Fri, 31 Aug 2018 22:36:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5F5B42C6A8; Fri, 31 Aug 2018 22:36:52 +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.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 F18D12BF2F for ; Fri, 31 Aug 2018 22:36:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727453AbeIACqY (ORCPT ); Fri, 31 Aug 2018 22:46:24 -0400 Received: from mail-pl1-f195.google.com ([209.85.214.195]:32916 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726915AbeIACqX (ORCPT ); Fri, 31 Aug 2018 22:46:23 -0400 Received: by mail-pl1-f195.google.com with SMTP id b92-v6so1035410plb.0 for ; Fri, 31 Aug 2018 15:36:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ozha6QqmfT5JrU9j0wVw3+1nSMpz8bliiwskTMqxkvk=; b=VFpVhvWNmNQ0tnQJVS9VlUKO3nhcG+Yxu47uMWjhdAiu3NSPNIdvhb3BlkriJ89cqP 5UHg+F5j0EXchq4GSCH+UAFZoLGDQryKuQwNbzj8yvcHbmH5VJ5muTQVN4CUmrNCrvu9 zM8+SzWiEo3I7Cqy1Ml4mWIZ8lUuRmtjc5wsrUl3ay/G8uXp/rjiRnOjMo9eMKgDtQzJ ohLIcw7jc9zCGLGLKsUWEtPjD8TCWR8Kq82jlPRuJ/KB5wS3w2t1talSfnRe+NpBT3QC VQyP18ea0bpTrabccHf4BhMwQ43w7nURqtEq3LveYm9lBcCLzXQFL2m50b19/Um+FSGc Tbvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ozha6QqmfT5JrU9j0wVw3+1nSMpz8bliiwskTMqxkvk=; b=l5pZM+sQtjCuETXfXE/8XOq0i+K9FOmIa2FiEVaLvilCxppQPVH9yN+JT+w8T8k8xH FnwUc0Xa1uT4moqP1IGWW5A7v4E3yy87V0tU3FGpLM9uX3hK394pV3xyZkbQP+1sqr2C pdXJxVhEn0uy9GHqZmXxer/qTYiweWJeMpo9CJg99L2oGhWIZ/xDd/TwQe4kqNmwhJWG RLVhQDpWlkoR6tdHDi8n3M/BE11MxdY7n7smCklEfv8XA9NTRMjQWzHbaU49s9SMKNF/ hrWNZqC/p3e+YGCQwoEZMz4FWeSqLJoRYrsgq4ZTbxwBunS1ENSuzXUtPJp05jPDEw+A 1vPA== X-Gm-Message-State: APzg51DSqMNOlFUvsVx2g9I6STrHZBVqn8TbQP6n573TO6TqyIEzlAz7 70V0Xha48LiydMJ1BFZtW+TSimOZsNE= X-Google-Smtp-Source: ANB0VdZUQCK2ylhPTS/qkAmBYIM3t58rsCR4P21jYyJ+K2VX2IX6k5Xjkk14wJeW2lMsSzB+WGOtlw== X-Received: by 2002:a17:902:6909:: with SMTP id j9-v6mr17377354plk.196.1535755008841; Fri, 31 Aug 2018 15:36:48 -0700 (PDT) Received: from vader.thefacebook.com ([2620:10d:c090:200::4:9733]) by smtp.gmail.com with ESMTPSA id r19-v6sm43427403pgo.43.2018.08.31.15.36.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 Aug 2018 15:36:48 -0700 (PDT) From: Omar Sandoval To: linux-btrfs@vger.kernel.org Cc: kernel-team@fb.com Subject: [PATCH v5 2/6] mm: export add_swap_extent() Date: Fri, 31 Aug 2018 15:36:37 -0700 Message-Id: X-Mailer: git-send-email 2.18.0 In-Reply-To: References: Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Omar Sandoval Btrfs will need this for swap file support. Signed-off-by: Omar Sandoval --- mm/swapfile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/swapfile.c b/mm/swapfile.c index d3f95833d12e..51cb30de17bc 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2365,6 +2365,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 From patchwork Fri Aug 31 22:36:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Sandoval X-Patchwork-Id: 10584521 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 843DD112B for ; Fri, 31 Aug 2018 22:36:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 776242BB98 for ; Fri, 31 Aug 2018 22:36:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6C0D32C6A8; Fri, 31 Aug 2018 22:36:53 +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.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 5F0972C62F for ; Fri, 31 Aug 2018 22:36:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727490AbeIACq0 (ORCPT ); Fri, 31 Aug 2018 22:46:26 -0400 Received: from mail-pl1-f194.google.com ([209.85.214.194]:44182 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727212AbeIACqZ (ORCPT ); Fri, 31 Aug 2018 22:46:25 -0400 Received: by mail-pl1-f194.google.com with SMTP id ba4-v6so6051053plb.11 for ; Fri, 31 Aug 2018 15:36:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=XfhD1s+oXIFOuIlVNDkhy1zo7dmofYMPh5tHBE+eOHA=; b=TFlYeuiWXO1u3gTbtx37Znx4/wlZKMKdj1tCBSJ3HvSNQG8UlGEoFocF8ZCB31rLTs EHzxRgQoCxWjgaaKaqKVZoc/+TftxiCgS9xr6rc20Z1HkwFwX3ve4/5Kv1aZhUUifh6o 7wWagsd+p8aRQa2YdmoTRv4iN3BMUGktv1nwKG1KGz3r2E0aime1p2/vjIy7AhdkZruD TpLV/XNKJAZDLFjZII6IDlXM5ByXLfwnGww3h0AmY8e+d4Zb0u3sHmMjENpAnSq3FBpp aBGE2SxPBpeS1lfaGbmKIpEpSyibnpajmC2PpEeZ5Jf0j8XL4AqQ7udp0U5IffffgZRU cR9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=XfhD1s+oXIFOuIlVNDkhy1zo7dmofYMPh5tHBE+eOHA=; b=Zmo51DNwsB0AsXxK8kQGMqqtMsL+tOBkhUIVY44MX02vHrWHfqH7WQwdXMeJXMaw0Z UG3JoXH1X4JrBN/FGCOA/YhMxEO5zwIc5LABUbtKwcxM0hytoMhbu2Bg16LrgfjxXu49 Fzr671rPchG6k6TznLUq3laz/WRapWLi7PYxbC2dMlSp48DwoSzEs5t6SxiHcUOzaWRf bU0CKXYH8Dm0maC3VQxmraI0ShPaaXB+ZURwslwJ2oz7L067wNbLQOqPcUwyQuSKTxJb ck/feALCmH945R9t5mdpv3Y6N6z1PcCHTRsq2MN9d4PjpeRe8747BuzgUQzj8Tr2rnLK 6mKg== X-Gm-Message-State: APzg51BkzOZoDeM0pb0Co8ATnc/+y/28IESCUTaIFgrDBZGYk80Hi4rs zP8tISpbPRKDDr8kUwojjT4veahNAjg= X-Google-Smtp-Source: ANB0Vda8PFH/b9sJdbp9dh7hhNPZt6Heh+3EwBVKRlIgZxYcKvRyKG2or5DSqRe194097ShpvKnzrw== X-Received: by 2002:a17:902:b089:: with SMTP id p9-v6mr16743200plr.254.1535755009826; Fri, 31 Aug 2018 15:36:49 -0700 (PDT) Received: from vader.thefacebook.com ([2620:10d:c090:200::4:9733]) by smtp.gmail.com with ESMTPSA id r19-v6sm43427403pgo.43.2018.08.31.15.36.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 Aug 2018 15:36:49 -0700 (PDT) From: Omar Sandoval To: linux-btrfs@vger.kernel.org Cc: kernel-team@fb.com Subject: [PATCH v5 3/6] vfs: update swap_{,de}activate documentation Date: Fri, 31 Aug 2018 15:36:38 -0700 Message-Id: <012fd4557eca49e783f408cd115842c0bcd13410.1535754957.git.osandov@fb.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: References: Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Omar Sandoval The documentation for these functions is wrong in several ways: - swap_activate() is called with the inode locked - swap_activate() takes a swap_info_struct * and a sector_t * - swap_activate() can also return a positive number of extents it added itself - swap_deactivate() does not return anything Reviewed-by: Nikolay Borisov Signed-off-by: Omar Sandoval --- Documentation/filesystems/Locking | 17 +++++++---------- Documentation/filesystems/vfs.txt | 12 ++++++++---- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index efea228ccd8a..b970c8c2ee22 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -210,8 +210,9 @@ prototypes: int (*launder_page)(struct page *); int (*is_partially_uptodate)(struct page *, unsigned long, unsigned long); int (*error_remove_page)(struct address_space *, struct page *); - int (*swap_activate)(struct file *); - int (*swap_deactivate)(struct file *); + int (*swap_activate)(struct swap_info_struct *, struct file *, + sector_t *); + void (*swap_deactivate)(struct file *); locking rules: All except set_page_dirty and freepage may block @@ -235,8 +236,8 @@ putback_page: yes launder_page: yes is_partially_uptodate: yes error_remove_page: yes -swap_activate: no -swap_deactivate: no +swap_activate: yes +swap_deactivate: no ->write_begin(), ->write_end() and ->readpage() may be called from the request handler (/dev/loop). @@ -333,14 +334,10 @@ cleaned, or an error value if not. Note that in order to prevent the page getting mapped back in and redirtied, it needs to be kept locked across the entire operation. - ->swap_activate will be called with a non-zero argument on -files backing (non block device backed) swapfiles. A return value -of zero indicates success, in which case this file can be used for -backing swapspace. The swapspace operations will be proxied to the -address space operations. + ->swap_activate is called from sys_swapon() with the inode locked. ->swap_deactivate() will be called in the sys_swapoff() -path after ->swap_activate() returned success. +path after ->swap_activate() returned success. The inode is not locked. ----------------------- file_lock_operations ------------------------------ prototypes: diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 4b2084d0f1fb..40d6d6d4b76b 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -652,8 +652,9 @@ struct address_space_operations { unsigned long); void (*is_dirty_writeback) (struct page *, bool *, bool *); int (*error_remove_page) (struct mapping *mapping, struct page *page); - int (*swap_activate)(struct file *); - int (*swap_deactivate)(struct file *); + int (*swap_activate)(struct swap_info_struct *, struct file *, + sector_t *); + void (*swap_deactivate)(struct file *); }; writepage: called by the VM to write a dirty page to backing store. @@ -830,8 +831,11 @@ struct address_space_operations { swap_activate: Called when swapon is used on a file to allocate space if necessary and pin the block lookup information in - memory. A return value of zero indicates success, - in which case this file can be used to back swapspace. + memory. If this returns zero, the swap system will call the address + space operations ->readpage() and ->direct_IO(). Alternatively, this + may call add_swap_extent() and return the number of extents added, in + which case the swap system will use the provided blocks directly + instead of going through the filesystem. swap_deactivate: Called during swapoff on files where swap_activate was successful. From patchwork Fri Aug 31 22:36:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Sandoval X-Patchwork-Id: 10584523 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1F5B8920 for ; Fri, 31 Aug 2018 22:36:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1211C2BB98 for ; Fri, 31 Aug 2018 22:36:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 06A152C62F; Fri, 31 Aug 2018 22:36: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.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 628292BF2F for ; Fri, 31 Aug 2018 22:36:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727496AbeIACq0 (ORCPT ); Fri, 31 Aug 2018 22:46:26 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:34488 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727477AbeIACq0 (ORCPT ); Fri, 31 Aug 2018 22:46:26 -0400 Received: by mail-pl1-f196.google.com with SMTP id f6-v6so6078856plo.1 for ; Fri, 31 Aug 2018 15:36:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ppAym3IV0BPcn23QhnOSVR2wQH2WKBLDNIvVo+Wzwc4=; b=kJzmI+C5gMb47gx82zz217csW+9RNUd5NZEOG3sZMeSQ3tLUn7mbNQ34TL4nM4zC8c xUHZA2VKKaHhvCJnvYF1UhxYqlLseWUtU3Bc7x+qQjJJ58BpQHTksLoLYIPzxPLaIJ8S mFWEhUnlVAYZ7xAa3GUvpdPcHwf0JHk3RgJY6KC8V9Z3bmZfNRsNSIkix3ehQWRKZlPc RTXeLXRsKDNPu5J84aAkH/o/l6QF08k1rRA/vQXcf8BrJHxC2qfX/u/o5mYmra1akqaP 6pS5kZYR7/w0kmwb5Xszbsi09ZjLN/G0mhigoilWEc9S22kQ0ULlsCk+nLTzK48Tzs4Q 3Krw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ppAym3IV0BPcn23QhnOSVR2wQH2WKBLDNIvVo+Wzwc4=; b=RQ67rVEx77rrrUGPK7kW4S1rkCycPN+5ggTNo91j6CpGHfw++h72A9+gntUy/bqvfj ZUT1BnorWT3Zt5WxL8AiLdvwlk/ECQlyXjEkFMYN8YR1OX45ve+4vfX8pmbSFryLEoB1 CsybV3NpxX9hPY8sORdx56XMpXrBf52AFGyAqjcOkGDzb5jzvpE+PpcujOOZmNzYUIb5 QXAMdluJPC4M9dtEZtBHkrJ9Hr9PKje7lCb/8/ADgPP/OB0VKDcgcrR0UqyxrLGyjX9x NWVWLo+5ChrA0nh0xlFxFFCd2aof/9pLW+uFTKj3GGdprcAhrcl4LwrS/Y9hsWCRIw5Z N1og== X-Gm-Message-State: APzg51Cx7zOf5Jp2e2GAgtwQy67JN5Vn/XqMxCJ1ehgLFkPa8bk3LjVy lEG6Tpkg3W7gl/7aY1ndyEVomcGdnxY= X-Google-Smtp-Source: ANB0VdZJukEB5k26gNxIk60PXMQwEhsKFP+4g5MGzLQw57aFRZ2NMZYYUp5re2pCEq68O/Dv/xTR6A== X-Received: by 2002:a17:902:b902:: with SMTP id bf2-v6mr17731380plb.185.1535755010849; Fri, 31 Aug 2018 15:36:50 -0700 (PDT) Received: from vader.thefacebook.com ([2620:10d:c090:200::4:9733]) by smtp.gmail.com with ESMTPSA id r19-v6sm43427403pgo.43.2018.08.31.15.36.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 Aug 2018 15:36:50 -0700 (PDT) From: Omar Sandoval To: linux-btrfs@vger.kernel.org Cc: kernel-team@fb.com Subject: [PATCH v5 4/6] Btrfs: prevent ioctls from interfering with a swap file Date: Fri, 31 Aug 2018 15:36:39 -0700 Message-Id: X-Mailer: git-send-email 2.18.0 In-Reply-To: References: Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Omar Sandoval When a swap file is active, we must make sure that the extents of the file are not moved and that they don't become shared. That means that the following are not safe: - chattr +c (enable compression) - reflink - dedupe - snapshot - defrag - balance - device remove/replace/resize Don't allow those to happen on an active swap file. Balance and device remove/replace/resize in particular are disallowed entirely; in the future, we can relax this so that relocation skips/errors out only on chunks containing an active swap file. Note that we don't have to worry about chattr -C (disable nocow), which we ignore for non-empty files, because an active swapfile must be non-empty and can't be truncated. We also don't have to worry about autodefrag because it's only done on COW files. Truncate and fallocate are already taken care of by the generic code. Device add doesn't do relocation so it's not an issue, either. Signed-off-by: Omar Sandoval --- fs/btrfs/ctree.h | 6 ++++++ fs/btrfs/disk-io.c | 3 +++ fs/btrfs/ioctl.c | 51 ++++++++++++++++++++++++++++++++++++++++++---- fs/btrfs/volumes.c | 6 ++++++ 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 53af9f5253f4..1c767a6394ae 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1121,6 +1121,9 @@ struct btrfs_fs_info { u32 sectorsize; u32 stripesize; + /* Number of active swapfiles */ + atomic_t nr_swapfiles; + #ifdef CONFIG_BTRFS_FS_REF_VERIFY spinlock_t ref_verify_lock; struct rb_root block_tree; @@ -1285,6 +1288,9 @@ struct btrfs_root { spinlock_t qgroup_meta_rsv_lock; u64 qgroup_meta_rsv_pertrans; u64 qgroup_meta_rsv_prealloc; + + /* Number of active swapfiles */ + atomic_t nr_swapfiles; }; struct btrfs_file_private { diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5124c15705ce..50ee5cd3efae 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1187,6 +1187,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info, atomic_set(&root->log_batch, 0); refcount_set(&root->refs, 1); atomic_set(&root->will_be_snapshotted, 0); + atomic_set(&root->nr_swapfiles, 0); root->log_transid = 0; root->log_transid_committed = -1; root->last_log_commit = 0; @@ -2781,6 +2782,8 @@ int open_ctree(struct super_block *sb, fs_info->sectorsize = 4096; fs_info->stripesize = 4096; + atomic_set(&fs_info->nr_swapfiles, 0); + ret = btrfs_alloc_stripe_hash_table(fs_info); if (ret) { err = ret; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 63600dc2ac4c..cc230dcd32a4 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -290,6 +290,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) } else if (fsflags & FS_COMPR_FL) { const char *comp; + if (IS_SWAPFILE(inode)) { + ret = -ETXTBSY; + goto out_unlock; + } + binode->flags |= BTRFS_INODE_COMPRESS; binode->flags &= ~BTRFS_INODE_NOCOMPRESS; @@ -751,6 +756,12 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, if (!test_bit(BTRFS_ROOT_REF_COWS, &root->state)) return -EINVAL; + if (atomic_read(&root->nr_swapfiles)) { + btrfs_info(fs_info, + "cannot snapshot subvolume with active swapfile"); + return -ETXTBSY; + } + pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_KERNEL); if (!pending_snapshot) return -ENOMEM; @@ -1487,9 +1498,13 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, } inode_lock(inode); - if (do_compress) - BTRFS_I(inode)->defrag_compress = compress_type; - ret = cluster_pages_for_defrag(inode, pages, i, cluster); + if (IS_SWAPFILE(inode)) { + ret = -ETXTBSY; + } else { + if (do_compress) + BTRFS_I(inode)->defrag_compress = compress_type; + ret = cluster_pages_for_defrag(inode, pages, i, cluster); + } if (ret < 0) { inode_unlock(inode); goto out_ra; @@ -1585,6 +1600,12 @@ static noinline int btrfs_ioctl_resize(struct file *file, return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; } + if (atomic_read(&fs_info->nr_swapfiles)) { + btrfs_info(fs_info, "cannot resize with active swapfile"); + ret = -ETXTBSY; + goto out; + } + vol_args = memdup_user(arg, sizeof(*vol_args)); if (IS_ERR(vol_args)) { ret = PTR_ERR(vol_args); @@ -3538,6 +3559,11 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen, goto out_unlock; } + if (IS_SWAPFILE(src) || IS_SWAPFILE(dst)) { + ret = -ETXTBSY; + goto out_unlock; + } + tail_len = olen % BTRFS_MAX_DEDUPE_LEN; chunk_count = div_u64(olen, BTRFS_MAX_DEDUPE_LEN); if (chunk_count == 0) @@ -4234,6 +4260,11 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src, goto out_unlock; } + if (IS_SWAPFILE(src) || IS_SWAPFILE(inode)) { + ret = -ETXTBSY; + goto out_unlock; + } + /* determine range to clone */ ret = -EINVAL; if (off + len > src->i_size || off + len < off) @@ -4712,7 +4743,13 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info, if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) { ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; } else { - ret = btrfs_dev_replace_by_ioctl(fs_info, p); + if (atomic_read(&fs_info->nr_swapfiles)) { + btrfs_info(fs_info, + "cannot replace device with active swapfile"); + ret = -ETXTBSY; + } else { + ret = btrfs_dev_replace_by_ioctl(fs_info, p); + } clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); } break; @@ -4972,6 +5009,12 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) locked: BUG_ON(!test_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)); + if (atomic_read(&fs_info->nr_swapfiles)) { + btrfs_info(fs_info, "cannot balance with active swapfile"); + ret = -ETXTBSY; + goto out_unlock; + } + if (arg) { bargs = memdup_user(arg, sizeof(*bargs)); if (IS_ERR(bargs)) { diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index da86706123ff..c03ef5322689 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1863,6 +1863,12 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, u64 num_devices; int ret = 0; + if (atomic_read(&fs_info->nr_swapfiles)) { + btrfs_info(fs_info, + "cannot remove device with active swapfile"); + return -ETXTBSY; + } + mutex_lock(&uuid_mutex); num_devices = fs_devices->num_devices; From patchwork Fri Aug 31 22:36:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Sandoval X-Patchwork-Id: 10584525 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B8AFB920 for ; Fri, 31 Aug 2018 22:36:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ACDAC2BB98 for ; Fri, 31 Aug 2018 22:36:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A12C82C6A8; Fri, 31 Aug 2018 22:36:55 +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.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 2F9922BB98 for ; Fri, 31 Aug 2018 22:36:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727518AbeIACq2 (ORCPT ); Fri, 31 Aug 2018 22:46:28 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:38130 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727477AbeIACq1 (ORCPT ); Fri, 31 Aug 2018 22:46:27 -0400 Received: by mail-pl1-f196.google.com with SMTP id u11-v6so6068080plq.5 for ; Fri, 31 Aug 2018 15:36:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8jDpedEqicozuO01+jFH4PvqWHaQTTX9H8llM2PBZJ8=; b=OwTEABZqWtF+xjYyDNUMX7j0L/IjIWLg4KrQDNX27oZE5EMP+/4skk/DdD4Zg4E/hZ OyMpDUDX+UcoEb3gYe2WIO18MCgrsLJ9t5xSJB1XyFuTlBoiPVmNCr6L1lQsns+GlPsD hNrvIxsEfuMdfUoQX5f+8N85Fl5LKJaxZhun58illWJW1liXZj94Pji9dcwD31sIUcgI bq31NwErUlyTnMkN2JxxgH0HieCJTsueYzZ1W6SCl95zcw9zgqMeccAb601H9KKs4Mki cEivBlqKMy/Q/jYvMYwVgiWaut0wZ64jKJF4H9mawWJImlYblDz8pU2XA0S2fQIiDK1t 4Axw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8jDpedEqicozuO01+jFH4PvqWHaQTTX9H8llM2PBZJ8=; b=SwWQ2A6B4ci1Dp1Zci6tFPRR8CSj229ljOu/bSH/c8Tpb1BX/iS3kvtvJpFp1lZyzH 89u+8R0L0gSjlKTfCpL0JZhl2ElHMMGHH3dVc4H7X6YmdBoq15xFggde4FRiK9LRGy8H Dpzexsc9cDAkQr1LSurXjWe7eND3YvDdYlwLBMA+bQ0S8rWLux8PqqMkxQJOHi2Kstni Kd595nKYwbGbsdmlSiWVR/vBmEaqblhokUafx8h40s33xIREmQ8v54xHXG5cJ2tSKNTM aqQxnzVXrdceqtlzc6lKTsl+pVSDolbiuQMMoJAX0tMHmNa3qJ8nbuovZohzgl9ltv9I gxnQ== X-Gm-Message-State: APzg51BZ+7aucrv9mxWIzDfLqbp06R63kaeRvXJhmOI6H584ZOBBuqZY 9T0ltQNVaRVwx+8ZTYa2OCUsFj4z5Gw= X-Google-Smtp-Source: ANB0VdYI/O8EXLowhM1oT8xK44BeeqfZLepEukLcn6e7foC3V1FFoHGPpjT/nbZH8HEapsDxPc5o6w== X-Received: by 2002:a17:902:7c07:: with SMTP id x7-v6mr16238866pll.113.1535755012075; Fri, 31 Aug 2018 15:36:52 -0700 (PDT) Received: from vader.thefacebook.com ([2620:10d:c090:200::4:9733]) by smtp.gmail.com with ESMTPSA id r19-v6sm43427403pgo.43.2018.08.31.15.36.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 Aug 2018 15:36:51 -0700 (PDT) From: Omar Sandoval To: linux-btrfs@vger.kernel.org Cc: kernel-team@fb.com Subject: [PATCH v5 5/6] Btrfs: rename get_chunk_map() and make it non-static Date: Fri, 31 Aug 2018 15:36:40 -0700 Message-Id: X-Mailer: git-send-email 2.18.0 In-Reply-To: References: Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Omar Sandoval The Btrfs swap code is going to need it, so give it a btrfs_ prefix and make it non-static. Signed-off-by: Omar Sandoval --- fs/btrfs/volumes.c | 22 +++++++++++----------- fs/btrfs/volumes.h | 9 +++++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index c03ef5322689..0aa8aff6774b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2712,8 +2712,8 @@ static int btrfs_del_sys_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset) return ret; } -static struct extent_map *get_chunk_map(struct btrfs_fs_info *fs_info, - u64 logical, u64 length) +struct extent_map *btrfs_get_chunk_map(struct btrfs_fs_info *fs_info, + u64 logical, u64 length) { struct extent_map_tree *em_tree; struct extent_map *em; @@ -2750,7 +2750,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans, u64 chunk_offset) int i, ret = 0; struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; - em = get_chunk_map(fs_info, chunk_offset, 1); + em = btrfs_get_chunk_map(fs_info, chunk_offset, 1); if (IS_ERR(em)) { /* * This is a logic error, but we don't want to just rely on the @@ -4884,7 +4884,7 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans, int i = 0; int ret = 0; - em = get_chunk_map(fs_info, chunk_offset, chunk_size); + em = btrfs_get_chunk_map(fs_info, chunk_offset, chunk_size); if (IS_ERR(em)) return PTR_ERR(em); @@ -5026,7 +5026,7 @@ int btrfs_chunk_readonly(struct btrfs_fs_info *fs_info, u64 chunk_offset) int miss_ndevs = 0; int i; - em = get_chunk_map(fs_info, chunk_offset, 1); + em = btrfs_get_chunk_map(fs_info, chunk_offset, 1); if (IS_ERR(em)) return 1; @@ -5086,7 +5086,7 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len) struct map_lookup *map; int ret; - em = get_chunk_map(fs_info, logical, len); + em = btrfs_get_chunk_map(fs_info, logical, len); if (IS_ERR(em)) /* * We could return errors for these cases, but that could get @@ -5132,7 +5132,7 @@ unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info, struct map_lookup *map; unsigned long len = fs_info->sectorsize; - em = get_chunk_map(fs_info, logical, len); + em = btrfs_get_chunk_map(fs_info, logical, len); if (!WARN_ON(IS_ERR(em))) { map = em->map_lookup; @@ -5149,7 +5149,7 @@ int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info, u64 logical, u64 len) struct map_lookup *map; int ret = 0; - em = get_chunk_map(fs_info, logical, len); + em = btrfs_get_chunk_map(fs_info, logical, len); if(!WARN_ON(IS_ERR(em))) { map = em->map_lookup; @@ -5308,7 +5308,7 @@ static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info, /* discard always return a bbio */ ASSERT(bbio_ret); - em = get_chunk_map(fs_info, logical, length); + em = btrfs_get_chunk_map(fs_info, logical, length); if (IS_ERR(em)) return PTR_ERR(em); @@ -5634,7 +5634,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, return __btrfs_map_block_for_discard(fs_info, logical, *length, bbio_ret); - em = get_chunk_map(fs_info, logical, *length); + em = btrfs_get_chunk_map(fs_info, logical, *length); if (IS_ERR(em)) return PTR_ERR(em); @@ -5933,7 +5933,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start, u64 rmap_len; int i, j, nr = 0; - em = get_chunk_map(fs_info, chunk_start, 1); + em = btrfs_get_chunk_map(fs_info, chunk_start, 1); if (IS_ERR(em)) return -EIO; diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 23e9285d88de..d68c8a05a774 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -465,6 +465,15 @@ unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info, int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans, u64 chunk_offset, u64 chunk_size); int btrfs_remove_chunk(struct btrfs_trans_handle *trans, u64 chunk_offset); +/** + * btrfs_get_chunk_map() - Find the mapping containing the given logical extent. + * @logical: Logical block offset in bytes. + * @length: Length of extent in bytes. + * + * Return: Chunk mapping or ERR_PTR. + */ +struct extent_map *btrfs_get_chunk_map(struct btrfs_fs_info *fs_info, + u64 logical, u64 length); static inline void btrfs_dev_stat_inc(struct btrfs_device *dev, int index) From patchwork Fri Aug 31 22:36:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Sandoval X-Patchwork-Id: 10584527 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3A3D4174A for ; Fri, 31 Aug 2018 22:36:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2CABC2BB98 for ; Fri, 31 Aug 2018 22:36:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 20B932C62F; Fri, 31 Aug 2018 22:36:56 +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.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 7B1CB2BF2F for ; Fri, 31 Aug 2018 22:36:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727531AbeIACq3 (ORCPT ); Fri, 31 Aug 2018 22:46:29 -0400 Received: from mail-pl1-f194.google.com ([209.85.214.194]:44187 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727501AbeIACq2 (ORCPT ); Fri, 31 Aug 2018 22:46:28 -0400 Received: by mail-pl1-f194.google.com with SMTP id ba4-v6so6051092plb.11 for ; Fri, 31 Aug 2018 15:36:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=xpf+278WIk8ts6h3C7uTns1U3fJgNPa5ypepViUclI4=; b=DeDLVgvuxZ18dp6NvBvQtDsoFrn22jXyCXCGH+uQvvYBVU42tncnHj0T/XgubUiCMN q5bKBtILn7dQDJvDZNfvVVDMYDImpGDHxh8nHTlA80mZQ+rdthpGc2ZjrjQW7BzX68m6 GZFZh15VivwlwHv7DgU13XfXZprJ3qVTx6jlFbm34/JjzpnUQxT+bcNGK640qFgpUlbJ RcRVRmH3yCvHv3wcE4NGUob1bkxD2lntSNN1HxcpCun5NmLhX8w6xxEelYotg5b1+K4C Krl5v8Nw2KqHhRBNQh2394RxjLfJ9A35i/UQMgmJSaIeOkegQAdMeM0YlHT+RZEywnVN ToUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=xpf+278WIk8ts6h3C7uTns1U3fJgNPa5ypepViUclI4=; b=mL/LNXfGvkr5KWyq/MZGL8do+U2vCXiNCMbt79IKMfNQdR/OeBHIkmhAUdcApRJQEf o+upbOAbxijZyNBZOC6HYX6e4WDWzvuhKPzk82BV8qBY0VFvBPDUcAXuvvJ22GbaWzNK e19ab6vwreKoPNMBJV+J0iYh794p1XjA3aqK0ai7RcaneEscG3PIweMaRxnx7OtGXFRQ CQ8xSvT943+S5tQFcRWyUWJiwd/04e89XtKRMfDiCA/bnO0PSfAdgevub3vvkMXb7rDn 8CiHI3jNgVyg9t8jXKST4/4A1MUfIttgZqJR7SG76xjs6K1jc99w9D5qPJySs0lwTCaA 335Q== X-Gm-Message-State: APzg51Cs8OYuDijQGCEHICIXmqDFX+NkJbVVj+oRVkcEQqG1xg50XGmn rCj5IQuKdiEEyig2d0unBXBi6bYxb7o= X-Google-Smtp-Source: ANB0VdZIeyAQVBrCgILkj3c9aK+aj8QsBwZ+JqM+F6Mc9WvEwSQgVcKQH4p4AgwaPG6JG8Yf9yPhsg== X-Received: by 2002:a17:902:42e2:: with SMTP id h89-v6mr17157749pld.69.1535755013229; Fri, 31 Aug 2018 15:36:53 -0700 (PDT) Received: from vader.thefacebook.com ([2620:10d:c090:200::4:9733]) by smtp.gmail.com with ESMTPSA id r19-v6sm43427403pgo.43.2018.08.31.15.36.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 Aug 2018 15:36:52 -0700 (PDT) From: Omar Sandoval To: linux-btrfs@vger.kernel.org Cc: kernel-team@fb.com Subject: [PATCH v5 6/6] Btrfs: support swap files Date: Fri, 31 Aug 2018 15:36:41 -0700 Message-Id: X-Mailer: git-send-email 2.18.0 In-Reply-To: References: Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Omar Sandoval Implement the swap file a_ops on Btrfs. Activation needs to make sure that the file can be used as a swap file, which currently means it must be fully allocated as nocow with no compression on one device. It also sets up the swap extents directly with add_swap_extent(), so export it. Signed-off-by: Omar Sandoval --- fs/btrfs/inode.c | 232 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9357a19d2bff..c0409e632768 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "ctree.h" #include "disk-io.h" @@ -10437,6 +10438,235 @@ void btrfs_set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end) } } +struct btrfs_swap_info { + u64 start; + u64 block_start; + u64 block_len; + u64 lowest_ppage; + u64 highest_ppage; + unsigned long nr_pages; + int nr_extents; +}; + +static int btrfs_add_swap_extent(struct swap_info_struct *sis, + struct btrfs_swap_info *bsi) +{ + unsigned long nr_pages; + u64 first_ppage, first_ppage_reported, next_ppage; + int ret; + + first_ppage = ALIGN(bsi->block_start, PAGE_SIZE) >> PAGE_SHIFT; + next_ppage = ALIGN_DOWN(bsi->block_start + bsi->block_len, + PAGE_SIZE) >> PAGE_SHIFT; + + if (first_ppage >= next_ppage) + return 0; + nr_pages = next_ppage - first_ppage; + + first_ppage_reported = first_ppage; + if (bsi->start == 0) + first_ppage_reported++; + if (bsi->lowest_ppage > first_ppage_reported) + bsi->lowest_ppage = first_ppage_reported; + if (bsi->highest_ppage < (next_ppage - 1)) + bsi->highest_ppage = next_ppage - 1; + + ret = add_swap_extent(sis, bsi->nr_pages, nr_pages, first_ppage); + if (ret < 0) + return ret; + bsi->nr_extents += ret; + bsi->nr_pages += nr_pages; + return 0; +} + +static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file, + sector_t *span) +{ + struct inode *inode = file_inode(file); + struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; + struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; + struct extent_state *cached_state = NULL; + struct extent_map *em = NULL; + struct btrfs_device *device = NULL; + struct btrfs_swap_info bsi = { + .lowest_ppage = (sector_t)-1ULL, + }; + int ret = 0; + u64 isize = inode->i_size; + u64 start; + + /* + * If the swap file was just created, make sure delalloc is done. If the + * file changes again after this, the user is doing something stupid and + * we don't really care. + */ + ret = btrfs_wait_ordered_range(inode, 0, (u64)-1); + if (ret) + return ret; + + /* + * The inode is locked, so these flags won't change after we check them. + */ + if (BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS) { + btrfs_err(fs_info, "swapfile must not be compressed"); + return -EINVAL; + } + if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW)) { + btrfs_err(fs_info, "swapfile must not be copy-on-write"); + return -EINVAL; + } + + /* + * Balance or device remove/replace/resize can move stuff around from + * under us. The EXCL_OP flag makes sure they aren't running/won't run + * concurrently while we are mapping the swap extents, and the fs_info + * nr_swapfiles counter prevents them from running while the swap file + * is active and moving the extents. Note that this also prevents a + * concurrent device add which isn't actually necessary, but it's not + * really worth the trouble to allow it. + */ + if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) + return -EBUSY; + atomic_inc(&fs_info->nr_swapfiles); + /* + * Snapshots can create extents which require COW even if NODATACOW is + * set. We use this counter to prevent snapshots. We must increment it + * before walking the extents because we don't want a concurrent + * snapshot to run after we've already checked the extents. + */ + atomic_inc(&BTRFS_I(inode)->root->nr_swapfiles); + + lock_extent_bits(io_tree, 0, isize - 1, &cached_state); + start = 0; + while (start < isize) { + u64 end, logical_block_start, physical_block_start; + u64 len = isize - start; + + em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, start, len, 0); + if (IS_ERR(em)) { + ret = PTR_ERR(em); + goto out; + } + end = extent_map_end(em); + + if (em->block_start == EXTENT_MAP_HOLE) { + btrfs_err(fs_info, "swapfile must not have holes"); + ret = -EINVAL; + goto out; + } + if (em->block_start == EXTENT_MAP_INLINE) { + /* + * It's unlikely we'll ever actually find ourselves + * here, as a file small enough to fit inline won't be + * big enough to store more than the swap header, but in + * case something changes in the future, let's catch it + * here rather than later. + */ + btrfs_err(fs_info, "swapfile must not be inline"); + ret = -EINVAL; + goto out; + } + if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) { + btrfs_err(fs_info, "swapfile must not be compressed"); + ret = -EINVAL; + goto out; + } + + logical_block_start = em->block_start + (start - em->start); + len = min(len, em->len - (start - em->start)); + free_extent_map(em); + em = NULL; + + ret = can_nocow_extent(inode, start, &len, NULL, NULL, NULL); + if (ret < 0) { + goto out; + } else if (ret) { + ret = 0; + } else { + btrfs_err(fs_info, "swapfile must not be copy-on-write"); + ret = -EINVAL; + goto out; + } + + em = btrfs_get_chunk_map(fs_info, logical_block_start, len); + if (IS_ERR(em)) { + ret = PTR_ERR(em); + goto out; + } + + if (em->map_lookup->type & BTRFS_BLOCK_GROUP_PROFILE_MASK) { + btrfs_err(fs_info, "swapfile must have single data profile"); + ret = -EINVAL; + goto out; + } + + if (device == NULL) { + device = em->map_lookup->stripes[0].dev; + } else if (device != em->map_lookup->stripes[0].dev) { + btrfs_err(fs_info, "swapfile must be on one device"); + ret = -EINVAL; + goto out; + } + + physical_block_start = (em->map_lookup->stripes[0].physical + + (logical_block_start - em->start)); + len = min(len, em->len - (logical_block_start - em->start)); + free_extent_map(em); + em = NULL; + + if (bsi.block_len && + bsi.block_start + bsi.block_len == physical_block_start) { + bsi.block_len += len; + } else { + if (bsi.block_len) { + ret = btrfs_add_swap_extent(sis, &bsi); + if (ret) + goto out; + } + bsi.start = start; + bsi.block_start = physical_block_start; + bsi.block_len = len; + } + + start = end; + } + + if (bsi.block_len) + ret = btrfs_add_swap_extent(sis, &bsi); + +out: + if (!IS_ERR_OR_NULL(em)) + free_extent_map(em); + + unlock_extent_cached(io_tree, 0, isize - 1, &cached_state); + + if (ret) { + atomic_dec(&BTRFS_I(inode)->root->nr_swapfiles); + atomic_dec(&fs_info->nr_swapfiles); + } + + clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); + + if (ret) + return ret; + + if (device) + sis->bdev = device->bdev; + *span = bsi.highest_ppage - bsi.lowest_ppage + 1; + sis->max = bsi.nr_pages; + sis->pages = bsi.nr_pages - 1; + sis->highest_bit = bsi.nr_pages - 1; + return bsi.nr_extents; +} + +static void btrfs_swap_deactivate(struct file *file) +{ + struct inode *inode = file_inode(file); + + atomic_dec(&BTRFS_I(inode)->root->nr_swapfiles); + atomic_dec(&BTRFS_I(inode)->root->fs_info->nr_swapfiles); +} + static const struct inode_operations btrfs_dir_inode_operations = { .getattr = btrfs_getattr, .lookup = btrfs_lookup, @@ -10514,6 +10744,8 @@ static const struct address_space_operations btrfs_aops = { .releasepage = btrfs_releasepage, .set_page_dirty = btrfs_set_page_dirty, .error_remove_page = generic_error_remove_page, + .swap_activate = btrfs_swap_activate, + .swap_deactivate = btrfs_swap_deactivate, }; static const struct address_space_operations btrfs_symlink_aops = {