From patchwork Wed Dec 10 01:45:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Sandoval X-Patchwork-Id: 5466261 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1AF3BBEEA8 for ; Wed, 10 Dec 2014 01:53:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2DB2320125 for ; Wed, 10 Dec 2014 01:53:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 338F520121 for ; Wed, 10 Dec 2014 01:53:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756007AbaLJBxM (ORCPT ); Tue, 9 Dec 2014 20:53:12 -0500 Received: from mail-pa0-f53.google.com ([209.85.220.53]:38859 "EHLO mail-pa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754154AbaLJBqq (ORCPT ); Tue, 9 Dec 2014 20:46:46 -0500 Received: by mail-pa0-f53.google.com with SMTP id kq14so1729273pab.40 for ; Tue, 09 Dec 2014 17:46:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=KycFajZx0U0ANboUCRErRjMrgYHIe1AamyOME8BGnmE=; b=YrlfWtuRrii65L4a63MaHsDoy8xxlgQwRE4h+Bs2P8ofH+/MVkRP4MX6WqN5rCrvGJ mNjNpdL/QMHOQtomFWfHAKX/XBzbu8IMf9QtHXhKh+BGPwq9LNFkeVmVOK2k22vUNHfm NfYL24zVaV6pdadgR67fNqXaCIeS0xP0kzdSVLFpjnImut2VXgjP6steHPd7MkZOxAOQ 2wbR/xXWLfsIg3zBNf5H7e/kFJ4z1LRIGWtfF3PKZABKoTm2A3lyZLswTM6qIwMWusQe g2pCM9QdyjhdUiL+kfToQN/WqrV8h7NYctUykMivsT9bSGxFIpKwzyfpv/lCx/XtqDxS t8hw== X-Gm-Message-State: ALoCoQlnPTuwZb+5DsjhhRMAAoLyPGQIM2fn9wjVwwusuCqgWMPpASZKWArfKPQfOzv25qu4V6n5 X-Received: by 10.66.66.135 with SMTP id f7mr2290675pat.67.1418176005831; Tue, 09 Dec 2014 17:46:45 -0800 (PST) Received: from mew.localdomain (c-24-19-133-29.hsd1.wa.comcast.net. [24.19.133.29]) by mx.google.com with ESMTPSA id on1sm2602957pdb.32.2014.12.09.17.46.44 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 09 Dec 2014 17:46:45 -0800 (PST) From: Omar Sandoval To: Alexander Viro , Andrew Morton , Chris Mason , Josef Bacik , Trond Myklebust , Christoph Hellwig , David Sterba , linux-btrfs@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Omar Sandoval Subject: [RFC PATCH v3 5/7] btrfs: prevent ioctls from interfering with a swap file Date: Tue, 9 Dec 2014 17:45:46 -0800 Message-Id: X-Mailer: git-send-email 2.1.3 In-Reply-To: References: In-Reply-To: References: Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There are several ioctls which can work around constraints enforced by btrfs_swap_activate and lead to an unsafe situation. We cannot do any of the following on an active swap file in order to avoid creating compressed or shared extents: - chattr -C or +c - snapshot create - defrag - clone - dedup Signed-off-by: Omar Sandoval --- fs/btrfs/ctree.h | 3 +++ fs/btrfs/disk-io.c | 1 + fs/btrfs/ioctl.c | 35 +++++++++++++++++++++++++++++++---- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index fe69edd..38979b9 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1891,6 +1891,9 @@ struct btrfs_root { int send_in_progress; struct btrfs_subvolume_writers *subv_writers; atomic_t will_be_snapshoted; + + /* Number of active swapfiles */ + atomic_t nr_swapfiles; }; struct btrfs_ioctl_defrag_range_args { diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 1bf9f89..60094c4 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1265,6 +1265,7 @@ static void __setup_root(u32 nodesize, u32 sectorsize, u32 stripesize, atomic_set(&root->orphan_inodes, 0); atomic_set(&root->refs, 1); atomic_set(&root->will_be_snapshoted, 0); + atomic_set(&root->nr_swapfiles, 0); root->log_transid = 0; root->log_transid_committed = -1; root->last_log_commit = 0; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4399f0c..18fa95c 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -291,9 +291,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) } else { ip->flags |= BTRFS_INODE_NODATACOW; } - } else { + } else if (!IS_SWAPFILE(inode)) { /* - * Revert back under same assuptions as above + * Revert back under same assumptions as above. swap_activate + * checks that we don't swapon a copy-on-write file, but we also + * make sure that it doesn't become copy-on-write here. */ if (S_ISREG(mode)) { if (inode->i_size == 0) @@ -316,7 +318,12 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0); if (ret && ret != -ENODATA) goto out_drop; - } else if (flags & FS_COMPR_FL) { + } else if (flags & FS_COMPR_FL && !IS_SWAPFILE(inode)) { + /* + * Like nodatacow, swap_activate checks that we don't swapon a + * compressed file, so we shouldn't let it become compressed. + */ + const char *comp; ip->flags |= BTRFS_INODE_COMPRESS; @@ -330,7 +337,6 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) comp, strlen(comp), 0); if (ret) goto out_drop; - } else { ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0); if (ret && ret != -ENODATA) @@ -647,6 +653,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_err(root->fs_info, + "cannot create snapshot with active swapfile"); + return -ETXTBSY; + } + atomic_inc(&root->will_be_snapshoted); smp_mb__after_atomic(); btrfs_wait_nocow_write(root); @@ -1292,6 +1304,12 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, compress_type = range->compress_type; } + mutex_lock(&inode->i_mutex); + ret = IS_SWAPFILE(inode) ? -ETXTBSY : 0; + mutex_unlock(&inode->i_mutex); + if (ret) + return ret; + if (extent_thresh == 0) extent_thresh = 256 * 1024; @@ -2927,6 +2945,11 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 len, btrfs_double_lock(src, loff, dst, dst_loff, len); + if (IS_SWAPFILE(src) || IS_SWAPFILE(dst)) { + ret = -ETXTBSY; + goto out_unlock; + } + ret = extent_same_check_offsets(src, loff, len); if (ret) goto out_unlock; @@ -3644,6 +3667,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, mutex_lock(&src->i_mutex); } + ret = -ETXTBSY; + if (IS_SWAPFILE(src) || IS_SWAPFILE(inode)) + goto out_unlock; + /* determine range to clone */ ret = -EINVAL; if (off + len > src->i_size || off + len < off)