Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp1685707ybt; Thu, 9 Jul 2020 12:54:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyOqIYmBDrTGnyQlt+JBj+NcAvCs4M5oXJh7KWPS04PEv+LkHjsv4scBMTV599dx5l16lPO X-Received: by 2002:aa7:c1d8:: with SMTP id d24mr75572711edp.178.1594324496223; Thu, 09 Jul 2020 12:54:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594324496; cv=none; d=google.com; s=arc-20160816; b=OiMWO+0bKRrCP5CWBIqHJ1oeHqcFAY22+d7l96lL3nqhXNa0rm/fZ8kWxbQ1ZvRqmk 8PZYHqALOuz4meO/KciTcrmbJ1qgdLE1oz9V/2bPGOLcjKSWVavKCYdoz9JEx/las7gF 5yI1ewl5xTHtY0B58+B6N5L05KOtuHLE7SCJ7sKvQPoCRagN9RlLCsYTo/wpQHf6FyM6 bpDR95RflX7fvGpSCSN59Thp4dby3UUMz+vrxz+ZegjOq2DUPmL95w5vx7wn/ynop3OP Ekat/c3F4l/K05QReFowIVjE8UxrjEydYxHuShZ7Dsc1Cg3KQM8027GypRHiqKNt+GXo pBtg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:dkim-signature; bh=+/XxnKhf8VQXnWlmxkLfLTPJmNMo/X9aFiP13+Lo8YI=; b=MMZhBhFRd+rjvhRB9hnHvEZIwY3WWO7RtmVo17bXMWgLideFLPOftEFdDNVFq1qKjF WMNEOT65dypmZZ/Sd5Ul8xj5KZfTcOnWKePOpw/19cXDoZfqbbW3fdpJkuAqk5+Ls6GQ Kc4DFMaMy/+poiUN83gEkqhDXVhIY5X3ehpKZ55ayE1h57eB1YQA05pn60uEJDEtyuCK VRH/eBSSdutCmG30T+p2nDod9wepUBaDayOAd9t7WW6zrJUVBWT/tuxNdwuRuIBvGiK2 fkfVHbeY201e4NM/cVXVm046h/nkbhFtYvNy1HqzAGgC/phDhtBMoR5hQ5sXQYwGY6lv wSNQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b="h/H0yRKb"; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id v14si2619173edq.527.2020.07.09.12.54.33; Thu, 09 Jul 2020 12:54:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b="h/H0yRKb"; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726445AbgGITyO (ORCPT + 99 others); Thu, 9 Jul 2020 15:54:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39820 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726343AbgGITr6 (ORCPT ); Thu, 9 Jul 2020 15:47:58 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E08E4C08E763 for ; Thu, 9 Jul 2020 12:47:57 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id y9so1893144plr.9 for ; Thu, 09 Jul 2020 12:47:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=+/XxnKhf8VQXnWlmxkLfLTPJmNMo/X9aFiP13+Lo8YI=; b=h/H0yRKbuSfyI8puj/GfGNpcjE4q8yWyZ39S7u7IcbvSYgI4b91Twrik62nZGiY8/z vzOjVOI15upZpzR/91wpbk98WfhemXBOL8DnysODYMcDgtbDIUG7EO6XLwAxLx0SkTlF QuQjmm6XT0lnZviNNA1jOOUC2jD+UG5qvworuWF3RuQKUTvEWAjaiWPwi84RKPEfbi3m hFPycqByVMLVQymThzvU3TnnurvzfN7ul52dp57GX99wkXEEyn1d/4kXqFJDCSww1rkP NSAplp6KppOYzHSsEqJTRpsyYGTar0iKcIpip6VZw4atI9KNa17YKeOYmpjk2VYFGA+a 1cjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=+/XxnKhf8VQXnWlmxkLfLTPJmNMo/X9aFiP13+Lo8YI=; b=rUDBpbGX7rEAXjQ7SIpVg5V+iN6oF4MaUZAT4hL35BOxNBmP0Z6hC8ZTK4JqqQ//IO rLFPPs8ZNjWEojgnalbFeM9BpPzEQmmK4jkHy/YkyycL082r0O9lKiofAAeC7ye3AS3k S6MLX/laHaCpO+Zksj4fC5/+s0Ha6IGA3xfDMH1OlLFBnXh6diJzzolGEhc4VR+hTa2p Kxh11x18W7QKg157QSehwVL5mxCF365o8Yv6aH0fy6O45dVqBa2QEYMzO88kaOzKWeLM VgBfKuL5jnieZRdb5IrMYuRlTLN7+Xq9zmxfQ4WSNMV0K0doC6SqFfyiAxeU5WV5gvO1 w4+g== X-Gm-Message-State: AOAM533iuk/ArUL2+xOWEp52OhYuxG+fx3BDpGbn1qIAbS+ZZbi3KybI h4gYPltFO7A+IyFyD+MxLU8GkXllDrA= X-Received: by 2002:aa7:9e4e:: with SMTP id z14mr31139029pfq.256.1594324077224; Thu, 09 Jul 2020 12:47:57 -0700 (PDT) Date: Thu, 9 Jul 2020 19:47:47 +0000 In-Reply-To: <20200709194751.2579207-1-satyat@google.com> Message-Id: <20200709194751.2579207-2-satyat@google.com> Mime-Version: 1.0 References: <20200709194751.2579207-1-satyat@google.com> X-Mailer: git-send-email 2.27.0.383.g050319c2ae-goog Subject: [PATCH 1/5] fscrypt: Add functions for direct I/O support From: Satya Tangirala To: linux-fscrypt@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org Cc: Eric Biggers , Satya Tangirala Content-Type: text/plain; charset="UTF-8" Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org From: Eric Biggers Introduce fscrypt_dio_supported() to check whether a direct I/O request is unsupported due to encryption constraints, and fscrypt_limit_dio_pages() to check how many pages may be added to a bio being prepared for direct I/O. The IV_INO_LBLK_32 fscrypt policy introduces the possibility that DUNs in logically continuous file blocks might wrap from 0xffffffff to 0. Bios in which the DUN wraps around like this cannot be submitted. This is especially difficult to handle when block_size != PAGE_SIZE, since in that case the DUN can wrap in the middle of a page. For now, we add direct I/O support while using IV_INO_LBLK_32 policies only for the case when block_size == PAGE_SIZE. When IV_INO_LBLK_32 policy is used, fscrypt_dio_supported() rejects the bio when block_size != PAGE_SIZE. fscrypt_limit_dio_pages() returns the number of pages that may be added to the bio without causing the DUN to wrap around within the bio. Signed-off-by: Eric Biggers Signed-off-by: Satya Tangirala --- fs/crypto/crypto.c | 8 +++++ fs/crypto/inline_crypt.c | 72 ++++++++++++++++++++++++++++++++++++++++ include/linux/fscrypt.h | 19 +++++++++++ 3 files changed, 99 insertions(+) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index a52cf32733ab..b88d97618efb 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -69,6 +69,14 @@ void fscrypt_free_bounce_page(struct page *bounce_page) } EXPORT_SYMBOL(fscrypt_free_bounce_page); +/* + * Generate the IV for the given logical block number within the given file. + * For filenames encryption, lblk_num == 0. + * + * Keep this in sync with fscrypt_limit_dio_pages(). fscrypt_limit_dio_pages() + * needs to know about any IV generation methods where the low bits of IV don't + * simply contain the lblk_num (e.g., IV_INO_LBLK_32). + */ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, const struct fscrypt_info *ci) { diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index d7aecadf33c1..86788ee2b206 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "fscrypt_private.h" @@ -362,3 +363,74 @@ bool fscrypt_mergeable_bio_bh(struct bio *bio, return fscrypt_mergeable_bio(bio, inode, next_lblk); } EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh); + +/** + * fscrypt_dio_supported() - check whether a direct I/O request is unsupported + * due to encryption constraints + * @iocb: the file and position the I/O is targeting + * @iter: the I/O data segment(s) + * + * Return: true if direct I/O is supported + */ +bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter) +{ + const struct inode *inode = file_inode(iocb->ki_filp); + const unsigned int blocksize = i_blocksize(inode); + + /* If the file is unencrypted, no veto from us. */ + if (!fscrypt_needs_contents_encryption(inode)) + return true; + + /* We only support direct I/O with inline crypto, not fs-layer crypto */ + if (!fscrypt_inode_uses_inline_crypto(inode)) + return false; + + /* + * Since the granularity of encryption is filesystem blocks, the I/O + * must be block aligned -- not just disk sector aligned. + */ + if (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), blocksize)) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(fscrypt_dio_supported); + +/** + * fscrypt_limit_dio_pages() - limit I/O pages to avoid discontiguous DUNs + * @inode: the file on which I/O is being done + * @pos: the file position (in bytes) at which the I/O is being done + * @nr_pages: the number of pages we want to submit starting at @pos + * + * For direct I/O: limit the number of pages that will be submitted in the bio + * targeting @pos, in order to avoid crossing a data unit number (DUN) + * discontinuity. This is only needed for certain IV generation methods. + * + * This assumes block_size == PAGE_SIZE; see fscrypt_dio_supported(). + * + * Return: the actual number of pages that can be submitted + */ +int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, int nr_pages) +{ + const struct fscrypt_info *ci = inode->i_crypt_info; + u32 dun; + + if (!fscrypt_inode_uses_inline_crypto(inode)) + return nr_pages; + + if (nr_pages <= 1) + return nr_pages; + + if (!(fscrypt_policy_flags(&ci->ci_policy) & + FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) + return nr_pages; + + if (WARN_ON_ONCE(i_blocksize(inode) != PAGE_SIZE)) + return 1; + + /* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */ + + dun = ci->ci_hashed_ino + (pos >> inode->i_blkbits); + + return min_t(u64, nr_pages, (u64)U32_MAX + 1 - dun); +} diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index bb257411365f..9c65d949c611 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -559,6 +559,11 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, bool fscrypt_mergeable_bio_bh(struct bio *bio, const struct buffer_head *next_bh); +bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter); + +int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, + int nr_pages); + #else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ static inline bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode) @@ -587,6 +592,20 @@ static inline bool fscrypt_mergeable_bio_bh(struct bio *bio, { return true; } + +static inline bool fscrypt_dio_supported(struct kiocb *iocb, + struct iov_iter *iter) +{ + const struct inode *inode = file_inode(iocb->ki_filp); + + return !fscrypt_needs_contents_encryption(inode); +} + +static inline int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, + int nr_pages) +{ + return nr_pages; +} #endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ /** -- 2.27.0.383.g050319c2ae-goog