From patchwork Fri Apr 10 03:03:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 1268923 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=j5WFUSvf; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48z2sB5GCSz9sSj for ; Fri, 10 Apr 2020 13:03:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726699AbgDJDDk (ORCPT ); Thu, 9 Apr 2020 23:03:40 -0400 Received: from mail-yb1-f179.google.com ([209.85.219.179]:45067 "EHLO mail-yb1-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726582AbgDJDDk (ORCPT ); Thu, 9 Apr 2020 23:03:40 -0400 Received: by mail-yb1-f179.google.com with SMTP id g6so506012ybh.12 for ; Thu, 09 Apr 2020 20:03:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=XgWkK59e6sJoN6LQrG3dAjoc1RUK0RdWfL4SmOfSU5M=; b=j5WFUSvfwdkUeHAhYUJUnfn+19SkAqiugLxaCJS/CflK+ku5r/dNdY7YZQheDH4Ul1 cn2hkQF//rlwdFlWj9mPmHzbnSHli+uKkC8eOjk0OSnvRjtL1lEpBIYOUsXwZLkrtN0G n2wNqWIc+skpC09TQdNnOFBX86G1H5uNIvHPYXrgmqB/+rYi2KLspqFLxbYl/T1cqMLZ 1G5S/3Ue3vFMEXBzTZBldeJGbZmct2YI4ipREFw557KPdYRxoaSes7UV+TDiQ/cwNJPT LKdHfK9Ugml9b5o+76gYJwKuZ1YrmeWjc7ekRXA3CDhmoGkTdI6uk5G5j31/uQfnUqSF EuGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=XgWkK59e6sJoN6LQrG3dAjoc1RUK0RdWfL4SmOfSU5M=; b=LjQWj+34HTo96aqRK8e6OFKs/ZdWfUUqNBgzDVvQMPLCPNDIccuSyi7S4o5nt0Hq3A v6o5MCKuhSoCScPiFEqNCG0GWnHbXFWVT6cG/+977ytdUMlYu6YH86OkJpMzSqX44ui2 x815R9Xu9uiZnkDmbO9SpnvuZ7uOsZ3rBhGqNdjwZcYqNCYGRjot7kBkceIGoUIkVaWt ID6iU7wOahFp6UQrqg52CCem7tMM9H7d/LbscGumOUhbzh9GKnDEGKf3CKZelJrYvD86 i/eyNQijL9/2lFZPrDls+Z6PV3XAHjDDMV9wzQ2E4j4B0dRyPg1CaXcE5xuFxGWRv4yF f5OQ== X-Gm-Message-State: AGi0Pub9RpSk0LPsIzNLo+WFIPX4PfuxWGyZ+9JZLMuqaL2T2zv9d4yo AgIO7aKv6R+ZEAuyYY+Im1koEAOuW1NSXGncrIIedSJVgCY= X-Google-Smtp-Source: APiQypK0uRi6le57lWG26OB8kdPdBaFjJadqU/cirJFPx0ghgui2d3C/CLrQ6W6nV2GfOZs+NSebN2f0Q1CpX4ExSI8= X-Received: by 2002:a25:b78b:: with SMTP id n11mr5088645ybh.376.1586487819054; Thu, 09 Apr 2020 20:03:39 -0700 (PDT) MIME-Version: 1.0 From: Steve French Date: Thu, 9 Apr 2020 22:03:28 -0500 Message-ID: Subject: [PATCH][SMB3] add experimental support for swap over SMB3 To: CIFS Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Add experimental support for allowing a swap file to be on an SMB3 mount. There are use cases where swapping over a secure network filesystem is preferable. In some cases there are no local block devices large enough, and network block devices can be hard to setup and secure. And in some cases there are no local block devices at all (e.g. with the recent addition of remote boot over SMB3 mounts). There are various enhancements that can be added later e.g.: - doing a mandatory byte range lock over the swapfile (until the Linux VFS is modified to notify the file system that an open is for a swapfile, when the file can be opened "DENY_ALL" to prevent others from opening it). - pinning more buffers in the underlying transport to minimize memory allocations in the TCP stack under the fs - documenting how to create ACLs (on the server) to secure the swapfile (or adding additional tools to cifs-utils to make it easier) From b84f80c1fdec1989b14dc4a8a32f11b473d1c1b5 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 9 Apr 2020 21:42:18 -0500 Subject: [PATCH] smb3: enable swap on SMB3 mounts Add experimental support for allowing a swap file to be on an SMB3 mount. There are use cases where swapping over a secure network filesystem is preferable. In some cases there are no local block devices large enough, and network block devices can be hard to setup and secure. And in some cases there are no local block devices at all (e.g. with the recent addition of remote boot over SMB3 mounts). There are various enhancements that can be added later e.g.: - doing a mandatory byte range lock over the swapfile (until the Linux VFS is modified to notify the file system that an open is for a swapfile, when the file can be opened "DENY_ALL" to prevent others from opening it). - pinning more buffers in the underlying transport to minimize memory allocations in the TCP stack under the fs - documenting how to create ACLs (on the server) to secure the swapfile (or adding additional tools to cifs-utils to make it easier) Signed-off-by: Steve French Acked-by: Pavel Shilovsky Reviewed-by: Ronnie Sahlberg --- fs/cifs/cifsfs.c | 4 +++ fs/cifs/cifsglob.h | 1 + fs/cifs/file.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ fs/cifs/inode.c | 4 +++ 4 files changed, 70 insertions(+) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 94e3ed4850b5..c31f362fa098 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1208,6 +1208,10 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off, { unsigned int xid = get_xid(); ssize_t rc; + struct cifsFileInfo *cfile = dst_file->private_data; + + if (cfile->swapfile) + return -EOPNOTSUPP; rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff, len, flags); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7448e7202e7a..05dd3dea684b 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1313,6 +1313,7 @@ struct cifsFileInfo { struct tcon_link *tlink; unsigned int f_flags; bool invalidHandle:1; /* file closed via session abend */ + bool swapfile:1; bool oplock_break_cancelled:1; unsigned int oplock_epoch; /* epoch from the lease break */ __u32 oplock_level; /* oplock/lease level from the lease break */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5920820bfbd0..b40dd374d6f3 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -4808,6 +4808,60 @@ cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter) return -EINVAL; } +static int cifs_swap_activate(struct swap_info_struct *sis, + struct file *swap_file, sector_t *span) +{ + struct cifsFileInfo *cfile = swap_file->private_data; + struct inode *inode = swap_file->f_mapping->host; + unsigned long blocks; + long long isize; + + cifs_dbg(FYI, "swap activate\n"); + + spin_lock(&inode->i_lock); + blocks = inode->i_blocks; + isize = inode->i_size; + spin_unlock(&inode->i_lock); + if (blocks*512 < isize) { + pr_warn("swap activate: swapfile has holes\n"); + return -EINVAL; + } + *span = sis->pages; + + printk_once(KERN_WARNING "Swap support over SMB3 is experimental\n"); + + /* + * TODO: consider adding ACL (or documenting how) to prevent other + * users (on this or other systems) from reading it + */ + + + /* TODO: add sk_set_memalloc(inet) or similar */ + + if (cfile) + cfile->swapfile = true; + /* + * TODO: Since file already open, we can't open with DENY_ALL here + * but we could add call to grab a byte range lock to prevent others + * from reading or writing the file + */ + + return 0; +} + +static void cifs_swap_deactivate(struct file *file) +{ + struct cifsFileInfo *cfile = file->private_data; + + cifs_dbg(FYI, "swap deactivate\n"); + + /* TODO: undo sk_set_memalloc(inet will eventually be needed */ + + if (cfile) + cfile->swapfile = false; + + /* do we need to unpin (or unlock) the file */ +} const struct address_space_operations cifs_addr_ops = { .readpage = cifs_readpage, @@ -4821,6 +4875,13 @@ const struct address_space_operations cifs_addr_ops = { .direct_IO = cifs_direct_io, .invalidatepage = cifs_invalidate_page, .launder_page = cifs_launder_page, + /* + * TODO: investigate and if useful we could add an cifs_migratePage + * helper (under an CONFIG_MIGRATION) in the future, and also + * investigate and add an is_dirty_writeback helper if needed + */ + .swap_activate = cifs_swap_activate, + .swap_deactivate = cifs_swap_deactivate, }; /* diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8d01ec2dca66..8fbbdcdad8ff 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -2026,6 +2026,10 @@ cifs_revalidate_mapping(struct inode *inode) int rc; unsigned long *flags = &CIFS_I(inode)->flags; + /* swapfiles are not supposed to be shared */ + if (IS_SWAPFILE(inode)) + return 0; + rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable, TASK_KILLABLE); if (rc) -- 2.20.1