From nobody Fri Jun 12 18:37:52 2026 Received: from OS8PR02CU002.outbound.protection.outlook.com (mail-japanwestazon11012063.outbound.protection.outlook.com [40.107.75.63]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D90F38BF8D; Wed, 13 May 2026 10:04:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.75.63 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778666695; cv=fail; b=p02JY4zL2uIwb61GgiukiCSSSiMt9UWBhQ3ilkTWaMFglCUGaO4VXFyTtcguFQUKj57Q8MzM8fkKAYn7+eU5g0bzvdDeGnC93BxnhepanT9reCEanhN4hDsuYHwnUmcluVrHGsuUAshilg7bzRwugQofvR54HQVLxxNF+rnCV6c= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778666695; c=relaxed/simple; bh=hAlZhBoafID94WCU7fyyHehqL/3Ib/g4r2Utg9DbjuQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=vBCs/wyf7lWCFbbp/04pcaw3qs/+6V2vQkw5uF34sVlxZ5B3HvR2mFrYxIkGlM3mGxj7jnOI4McVw06tsO8sUFaT8wLtxo9R176FcZfk4e2X+rVEfMQNsELiKTi4Ia8JpOgYxgzyIRH7UvuVfD+iaskpaxwb3YS/eWQCs4REuKk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=vivo.com; spf=pass smtp.mailfrom=vivo.com; dkim=pass (2048-bit key) header.d=vivo.com header.i=@vivo.com header.b=Lin1GWcN; arc=fail smtp.client-ip=40.107.75.63 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=vivo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=vivo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=vivo.com header.i=@vivo.com header.b="Lin1GWcN" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=xgt0xVJH+sXTSOqnK2NzY+Og9wU5QyFVjopBn3I8mTSga2wKnxYLAy5DPmOL+CSdcwuUy7nVKm0WKwjiGuu2WXDuhC+y4MTesOSWT5v2eSlCjqsTs6JHgj3c+WTkuoENIcTY71QlnD/OcaUh7EFDfkYqeqRy4iEG5dH/ieR+dzMwR2jMgdlyAJTei4cHxQTP7LRqcivykLsDzeQv8zBVRArsIOKMhmneUk1Vf9kAN322Z7VHDjbh19KJdqsZt3P74MOjcbU0rEGqe0hVok1gWznspAH86lYzfjTP/jiMQg+t+zUaKwxhPRwCWKi5UJH3taDg/yE8RGyoa/6brLYIXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=5m1uc7/eiXDUKn+ZoocdI1FUxm3ZTVaYfTkV0yo4zNM=; b=zQo0dkLu10/WqiO/Ym32gSek5+GaoUCe5gB074iSm9VvwwlcWwLHa/n9iKMz9vw2WWO/8/byTDJf4wcyzENA2Sc2iBwDDY1XNuyvwqmwbAyU6Y0cE6z8EnWTkVaIF4KAITQ41e0QmxwCFSdhTzWqfuAYwv2du0/mhHZeSyGldacLIQZarUIGLJbZctveRH4lfSTQq2cvs4zONmZ5DNmGcbWBFqczcyZdRd3NGutMcx3g8dca1Ea3UZns78JbKOWn/mUG2B1kE7wDR1vCwjc7nYyJpaSA7t9tcRcU2+gQYhsoDHSQ9U4h3GEv4t4URlPeXaoK0ZPrCYETwC6XUA+hkQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=vivo.com; dmarc=pass action=none header.from=vivo.com; dkim=pass header.d=vivo.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vivo.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=5m1uc7/eiXDUKn+ZoocdI1FUxm3ZTVaYfTkV0yo4zNM=; b=Lin1GWcN9zagpgcsGUEGuOiZbDObaaHoAzwGlYxpp52gTHANJHbpZQ+dihAOmfHcYCSmZJBdhUCXLGB1NjBNbqP19/szJMSvCtUAhVlVbu6e2iljcPXKyjv6vHG7xKa0gPOXAEiKh+SAbfVv4NDFwn+tJ0U9A6fegtbsS9CLG5EM5FEq9v1Zo4xbk1x8TAw/m/GLmQUXz5OqFx7u1m6lZV211bQavWtxC3zBd3aJWxxppDSo2ee1t+HXYNWVHK1atLTDR7WwkLgYRQgz12KHxmUQxQ8B1kt+LGdVdZtvGGWDMIzek/EFspsZyNhUlv78s+5eQ7rPLt30mO2IkS28jw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=vivo.com; Received: from SEZPR06MB5576.apcprd06.prod.outlook.com (2603:1096:101:c9::14) by KL1PR06MB5884.apcprd06.prod.outlook.com (2603:1096:820:dd::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9913.11; Wed, 13 May 2026 10:04:46 +0000 Received: from SEZPR06MB5576.apcprd06.prod.outlook.com ([fe80::24bc:5613:3ffa:cb96]) by SEZPR06MB5576.apcprd06.prod.outlook.com ([fe80::24bc:5613:3ffa:cb96%6]) with mapi id 15.20.9913.009; Wed, 13 May 2026 10:04:46 +0000 From: LiaoYuanhong-vivo To: Eric Biggers , "Theodore Y. Ts'o" , Jaegeuk Kim , linux-fscrypt@vger.kernel.org (open list:FSCRYPT: FILE SYSTEM LEVEL ENCRYPTION SUPPORT), linux-kernel@vger.kernel.org (open list) Cc: Liao Yuanhong Subject: [PATCH 1/3] fscrypt: prepare software keys for filesystem-managed data units Date: Wed, 13 May 2026 18:04:28 +0800 Message-Id: <20260513100431.299904-2-liaoyuanhong@vivo.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260513100431.299904-1-liaoyuanhong@vivo.com> References: <20260513100431.299904-1-liaoyuanhong@vivo.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TP0P295CA0031.TWNP295.PROD.OUTLOOK.COM (2603:1096:910:4::12) To SEZPR06MB5576.apcprd06.prod.outlook.com (2603:1096:101:c9::14) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SEZPR06MB5576:EE_|KL1PR06MB5884:EE_ X-MS-Office365-Filtering-Correlation-Id: c6e515fd-0b15-47df-9a5d-08deb0d70ff0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|52116014|376014|22082099003|18002099003|11063799003|56012099003|38350700014; X-Microsoft-Antispam-Message-Info: /f+MsaqeBBoJC8Tp8R7rXgFDjposBLlK29bxHJTp5NnDSzpy2H41PFI7F/6iK8Pl80ZNCDft8FMSeWF3GiJocUqphqTo8IxG7/gnZ4WWzGTLru7s+OCfZ3+MNEY28d5RCqu3ymgPtTIFuesSiKGhG4/g+4O6WXL5LsdCtSdz8FD4Xu+D1+LZchmuEhMFaglp9VacsOE+Fv0A3TNh8VU5OId5NzPqTFivK2WGTGMJFF45a2bqoOyAgBF7pOJ/xzIYNNqbWKgOra8DMwgqYg6aoFeREaaBGk2sH9V8OJj3jqQ0MvB5J3ca4b/ILG+asHjUoJqaXkLL2k50fcoj/ml7CcUy6gPU2A0u9illYeNhyf+kr6p/h84pCjWG3D4hJizyAufGuoXVvAZbHozXi1F3rzn46UKRPZodOrPdp5LQ8vX2fTHIRninq0M7eXYVI+m39TqzmTkMTw4uLeGRgTKJJir3M+LRYpJ9JjoEgeLcJAQcM1irsKTfMWH/mu0Qy6WuCMUpTQvv6NVz8gFcJKUnIKhQWeLPR0IhNpxD0ocLO3Fy4dCg/wcGmUaHl0fglmDGxTZM6AF+g4icJof8tCzK/dDLrkl0aQ83JPkjEY0ny9FbpQObeZVUWwN3uqwydmrqWmzA1/Dzb0LFoXUSPzPFoZ1f6BGZ7SdLnt6o0N6kBCWFuWxID6yxVdblONQg+D4bcw2vSpBXo7hGmJ9j0JQeMzHLx85DDNKOjqDy8vL4V8M7+kb3gqDlm+EkBHkEUYo6 X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SEZPR06MB5576.apcprd06.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(52116014)(376014)(22082099003)(18002099003)(11063799003)(56012099003)(38350700014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?kjh2nlPZoGdKDv0Y5wTfusFgy57NQrDzCHesL3XZZAt25cffh1rfsnH7bSnE?= =?us-ascii?Q?zqyBFN8qhzFzd7J1n/XIwte34CpZ+teR1IfzPMokD2rZsNW3EgKxOEF+sZJm?= =?us-ascii?Q?cJ+j3qSL1qNa4wBnG930UkGotDDPsrcfvNb0pshjV7JSuocj50q4W6+SaFk7?= =?us-ascii?Q?368gfM3F34gERAeeYscvfVVBcR/yaPWTRQUO7ybFK0KLe571WtQpA0y0eouo?= =?us-ascii?Q?W/+DX5omN1drstWAEIo1zurPlYahoQCYVJqpeH9QmX0YH4gpVyiOWV/N2Mp5?= =?us-ascii?Q?bhR8NmdaoqOxeM0q48OLjdB0xWXxnPLSqprA9Au5C2wbeLhZUsxp9Q2fEIH+?= =?us-ascii?Q?VaRamgKbZSCyOOTvVW2g4/JpOnzIqQNsuTO4x99w+r4aCuWI3p+D+bcPMKOu?= =?us-ascii?Q?rWBBl2uvDa0V5Nmkv9NFV8TzGy0m33YODfRDSHn8xTkRfN3IKoKt3LdMYYWF?= =?us-ascii?Q?pw1vAvzqOz/ByVto7IfRf82oeB4Dc0mTwcFvQCTt75jnzvaN5eEPZFNHeWPt?= =?us-ascii?Q?L/VC3KBRjDUKMmIVuxSRzbx+2TtSJdR2fEIGUIdm8J8x9xPm6uk12C4F9CQL?= =?us-ascii?Q?Dn5LDE8d2ozuUHL6O1CAfYf3dMXkmYxNiS4+bss5+TM+i19l3+uMeTlOVAwe?= =?us-ascii?Q?LBp3R/IE0j22h4StItuylRPR+5Rar4q3xz7jAJUTOnoYVifHiaXolluiwFIt?= =?us-ascii?Q?MKpHfYN4QRPDKJuV9tauCriqhnX9tYY1NjqdpdTGTSJ4tuuJ6iqxgRCPcVZT?= =?us-ascii?Q?RVzd51kGAIuqbCGv1ZMpU8iU/lj1RcG+QH6miUl7IgPtPkFKNwseaZ1jue+x?= =?us-ascii?Q?PUBrkp+llSLqkZhbizwXTXCLh0cj1+nBw/fAwet/Zj71TuuW7sNssGk9DMbT?= =?us-ascii?Q?l3UI0KtVc94CmyKEGWZRcjBKfNlHH9PUi5wwfH9zMwbuRnjXQi5vj0ueEsWf?= =?us-ascii?Q?wKzwewoE/LBUdt9vWRZxp1hy69qIMJY5pvG1fQlBmZukb2zJ8bf7tmjiTrra?= =?us-ascii?Q?YJSdYtEgrsi0x3KYBJIp5Rdx4/7qPFr9uH8VpuQbaTZD0uNYApcH4XWE7+dC?= =?us-ascii?Q?mHVw2O8Ucv01w/4w3hG1C7EspWvhVf8Dn6mdTwdo4WDKsoAAPmq6LL8Sao52?= =?us-ascii?Q?9SjbbG+RYtRQzufKJH96fo4ySQwMIaeyneueQ7d6jedwzB1R73h2/hMpXuZB?= =?us-ascii?Q?Jc6Nmf0U9MUVRHVPhx2xEPosS6ABT0JrSMqtohizHggb3dKkacKWvyzVpxp/?= =?us-ascii?Q?GmRgj6RxYoUvozSOwmZDCQ7xYpi44JnEhZy9T616fhzqAQD8+WhywWO6aZHA?= =?us-ascii?Q?nx4ueTZAMGVAq6qRcduHg8YTMH24gTMTuNmZW/bhcaPRXHU82JZ5hoUk/Vv8?= =?us-ascii?Q?4putCDeurYsbLC33uJfSRvZnkGuirk+unV7Qszygt9N9LAcyzo0q2Up22rgh?= =?us-ascii?Q?kmTuoPUicHVHCdO6AD99Vu+HNIpiwTX3cMCpRLqmT5vlrZ20g3v20Y1wzSEn?= =?us-ascii?Q?9GRNgsxht45gFz1q1+D2OsxHoHQEn+IeyGuBAXjCKgAP9tG687t46E0kAkBl?= =?us-ascii?Q?FHsGii1cF4FFb48tJv/C2x5hRnU6SF4WSmA0b1VHkipewn6CAlllcDHQxQ6J?= =?us-ascii?Q?fF0Tb8h8MdGn/l8jMQ+WFoZkxVC66HQ7wMPe2KndAld09vlHVU6rgDZzGItK?= =?us-ascii?Q?eznCbL2xAIP2dQepI1skJ8MqBYTpCt8HsmTxinch/dn8Obu/49TqapxZm+dd?= =?us-ascii?Q?I2Npizb1IA=3D=3D?= X-OriginatorOrg: vivo.com X-MS-Exchange-CrossTenant-Network-Message-Id: c6e515fd-0b15-47df-9a5d-08deb0d70ff0 X-MS-Exchange-CrossTenant-AuthSource: SEZPR06MB5576.apcprd06.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 May 2026 10:04:46.6948 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 923e42dc-48d5-4cbe-b582-1a797a6412ed X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 7HnA2Cchm215VNv3m933tAR0Bq09fNCkiIh5o33J0DPAGKg47oTdawDB2heg7ZhDBabJfT2H0NMlS1NnM0SxbQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: KL1PR06MB5884 Content-Type: text/plain; charset="utf-8" From: Liao Yuanhong Some filesystems store small data regions inside filesystem metadata rather than submitting them through the normal bio path. F2FS inline data is one such case. When an encrypted file uses blk-crypto, these regions still need software fscrypt handling because no data bio is submitted for them. Add fscrypt_encrypt_data_unit_inplace() and fscrypt_decrypt_data_unit_inplace(). They use the same data-unit crypto path as fscrypt_encrypt_block_inplace() and fscrypt_decrypt_block_inplace(), but take a data-unit index instead of a filesystem logical block number. Also add fscrypt_inode_supports_data_unit_inplace() so filesystems can check whether an inode has a software transform available for this path. Factor the software skcipher setup into fscrypt_prepare_software_key(). The existing fscrypt_prepare_key() path now reuses it, and inline-crypto key setup can use it in addition to preparing the blk-crypto key. This lets an inline-crypto inode keep its normal blk-crypto contents path while also having a software transform for filesystem-managed data units. Signed-off-by: Liao Yuanhong --- fs/crypto/crypto.c | 63 +++++++++++++++++++++++++++++++++++++ fs/crypto/fscrypt_private.h | 3 +- fs/crypto/keysetup.c | 59 +++++++++++++++++++++++++--------- include/linux/fscrypt.h | 28 +++++++++++++++++ 4 files changed, 138 insertions(+), 15 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 570a2231c945..c43acbc8b4ea 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -208,6 +208,44 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct f= olio *folio, } EXPORT_SYMBOL(fscrypt_encrypt_pagecache_blocks); =20 +/** + * fscrypt_encrypt_data_unit_inplace() - Encrypt a data unit in-place + * @inode: The inode to which this data unit belongs + * @page: The page containing the data unit to encrypt + * @len: Size of data unit to encrypt. This must be a multiple of + * FSCRYPT_CONTENTS_ALIGNMENT. + * @offs: Byte offset within @page at which the data unit begins + * @index: Fscrypt data unit index within the file + * + * Return: 0 on success; -errno on failure + */ +int fscrypt_encrypt_data_unit_inplace(const struct inode *inode, + struct page *page, unsigned int len, + unsigned int offs, u64 index) +{ + const struct fscrypt_inode_info *ci =3D fscrypt_get_inode_info_raw(inode); + + if (!fscrypt_inode_supports_data_unit_inplace(inode)) + return -EOPNOTSUPP; + + return fscrypt_crypt_data_unit(ci, FS_ENCRYPT, index, page, page, len, + offs); +} +EXPORT_SYMBOL(fscrypt_encrypt_data_unit_inplace); + +bool fscrypt_inode_supports_data_unit_inplace(const struct inode *inode) +{ + const struct fscrypt_inode_info *ci =3D fscrypt_get_inode_info_raw(inode); + + if (!IS_ENABLED(CONFIG_FS_ENCRYPTION_INLINE_CRYPT)) + return false; + if (!ci) + return false; + /* pairs with smp_store_release() in fscrypt_prepare_software_key() */ + return smp_load_acquire(&ci->ci_enc_key.tfm); +} +EXPORT_SYMBOL(fscrypt_inode_supports_data_unit_inplace); + /** * fscrypt_encrypt_block_inplace() - Encrypt a filesystem block in-place * @inode: The inode to which this block belongs @@ -282,6 +320,31 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *fol= io, size_t len, } EXPORT_SYMBOL(fscrypt_decrypt_pagecache_blocks); =20 +/** + * fscrypt_decrypt_data_unit_inplace() - Decrypt a data unit in-place + * @inode: The inode to which this data unit belongs + * @page: The page containing the data unit to decrypt + * @len: Size of data unit to decrypt. This must be a multiple of + * FSCRYPT_CONTENTS_ALIGNMENT. + * @offs: Byte offset within @page at which the data unit begins + * @index: Fscrypt data unit index within the file + * + * Return: 0 on success; -errno on failure + */ +int fscrypt_decrypt_data_unit_inplace(const struct inode *inode, + struct page *page, unsigned int len, + unsigned int offs, u64 index) +{ + const struct fscrypt_inode_info *ci =3D fscrypt_get_inode_info_raw(inode); + + if (!fscrypt_inode_supports_data_unit_inplace(inode)) + return -EOPNOTSUPP; + + return fscrypt_crypt_data_unit(ci, FS_DECRYPT, index, page, page, len, + offs); +} +EXPORT_SYMBOL(fscrypt_decrypt_data_unit_inplace); + /** * fscrypt_decrypt_block_inplace() - Decrypt a filesystem block in-place * @inode: The inode to which this block belongs diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 8d3c278a7591..b5c0b881fd4b 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -236,7 +236,8 @@ struct fscrypt_symlink_data { * @tfm: crypto API transform object * @blk_key: key for blk-crypto * - * Normally only one of the fields will be non-NULL. + * Most users need only one prepared form. Inline-crypto users that also = need + * filesystem-layer software crypto for non-bio data regions may prepare b= oth. */ struct fscrypt_prepared_key { struct crypto_sync_skcipher *tfm; diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index ce327bfdada4..716911b97d8e 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -144,6 +144,23 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, c= onst u8 *raw_key, return ERR_PTR(err); } =20 +static int fscrypt_prepare_software_key(struct fscrypt_prepared_key *prep_= key, + const u8 *raw_key, + const struct fscrypt_inode_info *ci) +{ + struct crypto_sync_skcipher *tfm; + + /* pairs with smp_store_release() below */ + if (smp_load_acquire(&prep_key->tfm)) + return 0; + tfm =3D fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + /* pairs with smp_load_acquire() above */ + smp_store_release(&prep_key->tfm, tfm); + return 0; +} + /* * Prepare the crypto transform object or blk-crypto key in @prep_key, giv= en the * raw key, encryption mode (@ci->ci_mode), flag indicating which encrypti= on @@ -153,24 +170,12 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, = const u8 *raw_key, int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, const u8 *raw_key, const struct fscrypt_inode_info *ci) { - struct crypto_sync_skcipher *tfm; - if (fscrypt_using_inline_encryption(ci)) return fscrypt_prepare_inline_crypt_key(prep_key, raw_key, ci->ci_mode->keysize, false, ci); =20 - tfm =3D fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - /* - * Pairs with the smp_load_acquire() in fscrypt_is_key_prepared(). - * I.e., here we publish ->tfm with a RELEASE barrier so that - * concurrent tasks can ACQUIRE it. Note that this concurrency is only - * possible for per-mode keys, not for per-file keys. - */ - smp_store_release(&prep_key->tfm, tfm); - return 0; + return fscrypt_prepare_software_key(prep_key, raw_key, ci); } =20 /* Destroy a crypto transform object and/or blk-crypto key. */ @@ -190,6 +195,20 @@ int fscrypt_set_per_file_enc_key(struct fscrypt_inode_= info *ci, return fscrypt_prepare_key(&ci->ci_enc_key, raw_key, ci); } =20 +static int +fscrypt_prepare_inline_crypt_and_software_key(struct fscrypt_prepared_key = *prep_key, + const u8 *raw_key, + const struct fscrypt_inode_info *ci) +{ + int err; + + err =3D fscrypt_prepare_software_key(prep_key, raw_key, ci); + if (err) + return err; + return fscrypt_prepare_inline_crypt_key(prep_key, raw_key, + ci->ci_mode->keysize, false, ci); +} + static int setup_per_mode_enc_key(struct fscrypt_inode_info *ci, struct fscrypt_master_key *mk, struct fscrypt_prepared_key *keys, @@ -255,7 +274,16 @@ static int setup_per_mode_enc_key(struct fscrypt_inode= _info *ci, } fscrypt_hkdf_expand(&mk->mk_secret.hkdf, hkdf_context, hkdf_info, hkdf_infolen, mode_key, mode->keysize); - err =3D fscrypt_prepare_key(prep_key, mode_key, ci); + if (!use_hw_wrapped_key && fscrypt_using_inline_encryption(ci)) { + /* + * Filesystem-managed regions such as F2FS inline_data need the + * same contents key as a software tfm. + */ + err =3D fscrypt_prepare_inline_crypt_and_software_key(prep_key, + mode_key, ci); + } else { + err =3D fscrypt_prepare_key(prep_key, mode_key, ci); + } memzero_explicit(mode_key, mode->keysize); if (err) goto out_unlock; @@ -381,6 +409,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_ino= de_info *ci, FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) { err =3D fscrypt_setup_iv_ino_lblk_32_key(ci, mk); } else { + struct fscrypt_prepared_key *prep_key =3D &ci->ci_enc_key; u8 derived_key[FSCRYPT_MAX_RAW_KEY_SIZE]; =20 fscrypt_hkdf_expand(&mk->mk_secret.hkdf, @@ -388,6 +417,8 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_ino= de_info *ci, ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE, derived_key, ci->ci_mode->keysize); err =3D fscrypt_set_per_file_enc_key(ci, derived_key); + if (!err && fscrypt_using_inline_encryption(ci)) + err =3D fscrypt_prepare_software_key(prep_key, derived_key, ci); memzero_explicit(derived_key, ci->ci_mode->keysize); } if (err) diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 54712ec61ffb..3762a7526fcc 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -346,12 +346,20 @@ void fscrypt_enqueue_decrypt_work(struct work_struct = *); =20 struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio, size_t len, size_t offs, gfp_t gfp_flags); + +int fscrypt_encrypt_data_unit_inplace(const struct inode *inode, + struct page *page, unsigned int len, + unsigned int offs, u64 index); +bool fscrypt_inode_supports_data_unit_inplace(const struct inode *inode); int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *= page, unsigned int len, unsigned int offs, u64 lblk_num); =20 int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len, size_t offs); +int fscrypt_decrypt_data_unit_inplace(const struct inode *inode, + struct page *page, unsigned int len, + unsigned int offs, u64 index); int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *= page, unsigned int len, unsigned int offs, u64 lblk_num); @@ -519,6 +527,19 @@ static inline struct page *fscrypt_encrypt_pagecache_b= locks(struct folio *folio, return ERR_PTR(-EOPNOTSUPP); } =20 +static inline int fscrypt_encrypt_data_unit_inplace(const struct inode *in= ode, + struct page *page, unsigned int len, + unsigned int offs, u64 index) +{ + return -EOPNOTSUPP; +} + +static inline bool +fscrypt_inode_supports_data_unit_inplace(const struct inode *inode) +{ + return false; +} + static inline int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page, unsigned int len, @@ -533,6 +554,13 @@ static inline int fscrypt_decrypt_pagecache_blocks(str= uct folio *folio, return -EOPNOTSUPP; } =20 +static inline int fscrypt_decrypt_data_unit_inplace(const struct inode *in= ode, + struct page *page, unsigned int len, + unsigned int offs, u64 index) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page, unsigned int len, --=20 2.34.1 From nobody Fri Jun 12 18:37:52 2026 Received: from OS8PR02CU002.outbound.protection.outlook.com (mail-japanwestazon11012063.outbound.protection.outlook.com [40.107.75.63]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6280538F64E for ; Wed, 13 May 2026 10:04:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.75.63 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778666697; cv=fail; b=AwTjQMUpTlXvWOWF60k/FUH60kY+VTbJS5ZaxLaBGMIPvr8bjXXPnTLi1RjLHH2+NhuGaagUU13UZ9ARR8KUzWg/eeliGN+OihSydp9imy618Hzydj/cmgVO0fJtnMEsNa5r31taC1u21D4418QfmXC3xZIUhC2uwJE8RUl1e2U= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778666697; c=relaxed/simple; bh=X15+cjfJ294wF9UBV/jSNbwoFDaN2oVV4I2w4Bh6pMM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=jczU6nBx8a3k9kKJdQHSyNM15OOw/Dx4ZUe43IwSsqA3ghxf6+VU72GwSlorRzWAmFIKRpSO03obsbQvA0121lvmqSWvRUKu7hWiIxwzlQCHI+hGWSLuGRRYq/nc3BZDJUm9q1Ajm8isAWD9c2nmXQ9vCwzfBXDnY3S8JZqraRM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=vivo.com; spf=pass smtp.mailfrom=vivo.com; dkim=pass (2048-bit key) header.d=vivo.com header.i=@vivo.com header.b=WPXxe4hM; arc=fail smtp.client-ip=40.107.75.63 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=vivo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=vivo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=vivo.com header.i=@vivo.com header.b="WPXxe4hM" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=i+lHxDlKcR3SERfk5ha6GXKQbMkGXYZH6J97z6wMQbrTtAR6PyNhpplb7tbnx5LT9AcdtVWHuTcB5Yi6pOAtuvNr0AWSnlSNLM9zYQ6y52fMiE21YwxhXAqXj0fwjuWl7ckJ1U3O2Tqj/fRsi/dKiSBfWUiUVR21YDJou4BMKE6z3PVwilVF4AzHh9CJxKz0+JQRGs3PHrCC1c91seYZ+MjPFp9+YzFY6wNbPkUDLKGzutH4cvU45C6nXZR9emmVxixE1BqyQVLicRhZXrne/pBAafKfZz5wT/fwgKgtEcL+PReFU8cEhZktGJTqndHWOFGqGqptEQj3+SiKCbiYjw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Cx3PtBAGYvPLmnhbJ5L2FS5TvaxHzPmXyvdJ7BU6bYk=; b=gXsb7ZVezRI/BC5vNS32x1KolYu8t1uxpdcxKsoPgCmzhmGD324QEbZ77yNvfi0b8H14erJ66tD5Lz6QZ4Thb1WSIxeSf7VC6tQdi/lrofylKYRrJ6ID4YPoZ1+frIHe2zOyHDOQlUJCx+q6j5duIGTbqlpZsI+IrczJjMlzyRMHLeMPNNa+hxX5GA2vLTz6EwUe/SKAShkA3BjpbRRBuq9Hsd0IUyiPzcZX1ytP+tbUqKcECTXlG/v+0Moe7HBhhiFLpx774RaGwcoWJH4ZBNXvu1swwnp+DYPdkveHTYKLeVdeeU8HqXgRnuSoG9pN61LQ62LIEUM+vsKWrBM49Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=vivo.com; dmarc=pass action=none header.from=vivo.com; dkim=pass header.d=vivo.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vivo.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Cx3PtBAGYvPLmnhbJ5L2FS5TvaxHzPmXyvdJ7BU6bYk=; b=WPXxe4hMdSVfLPp0CQXqR1MJA094j26oq6VrbSRCkI7nwiv5D0Y7wYEMi724ZTr2GBDA/DcFnr8iTfOOdBIngTMOPSSRtSlPyBMnnlp41sMKmtnh3dm7AuEDTxi7S5RbdIsHS8n4Uevp6eo5hnUo6A+Dmdc5Uor19XD1patSK/2niGVy6BomfBSKvOstnc/sV/G3ItSqUhe/SH7fToj8XVgtdXtIJe/XB3mIzXCR3W2ac34lMB5hRrp7uc9U5jmHJSy9qIPMBtS+uNpaDW1lTYFVxniXvWbZmtEIzCzXD2i5qvs/OAol9Btewc8ZLPrNF95mzeMRQdvdGqlP93wdCQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=vivo.com; Received: from SEZPR06MB5576.apcprd06.prod.outlook.com (2603:1096:101:c9::14) by KL1PR06MB5884.apcprd06.prod.outlook.com (2603:1096:820:dd::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9913.11; Wed, 13 May 2026 10:04:50 +0000 Received: from SEZPR06MB5576.apcprd06.prod.outlook.com ([fe80::24bc:5613:3ffa:cb96]) by SEZPR06MB5576.apcprd06.prod.outlook.com ([fe80::24bc:5613:3ffa:cb96%6]) with mapi id 15.20.9913.009; Wed, 13 May 2026 10:04:50 +0000 From: LiaoYuanhong-vivo To: Jaegeuk Kim , Chao Yu , linux-f2fs-devel@lists.sourceforge.net (open list:F2FS FILE SYSTEM), linux-kernel@vger.kernel.org (open list) Cc: Liao Yuanhong Subject: [PATCH 2/3] f2fs: support encrypted inline data Date: Wed, 13 May 2026 18:04:29 +0800 Message-Id: <20260513100431.299904-3-liaoyuanhong@vivo.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260513100431.299904-1-liaoyuanhong@vivo.com> References: <20260513100431.299904-1-liaoyuanhong@vivo.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TP0P295CA0031.TWNP295.PROD.OUTLOOK.COM (2603:1096:910:4::12) To SEZPR06MB5576.apcprd06.prod.outlook.com (2603:1096:101:c9::14) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SEZPR06MB5576:EE_|KL1PR06MB5884:EE_ X-MS-Office365-Filtering-Correlation-Id: 59d7c160-7e2e-4e18-04d3-08deb0d71200 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|52116014|376014|22082099003|18002099003|11063799003|3023799003|56012099003|38350700014; X-Microsoft-Antispam-Message-Info: i5lxO3cLPfegMoT1h6SUp+h/tBNgOcZVqGd/ecJfVz7m7uaFafunBBR7kFtG627DqX6RYLRuD4yxMvWWQcGphMvO9eeQXYI23s4EerVgwCOHAmwyo/2lWQYtXEAR1s4rt8uxj9wSnCODAFWaVNkBinH86P8iSOw4ViKz/9wn8qzXlEI2C0ui1ooZqhf3vwWPY9vWPS3Tfdl1ld+9bCRfnlEUYQ4Cp4Af4rru1Xi/1/VUpNs0ip/BetZk8Nj28i7dV4x0dzjgNTgB800zPQhLuVBCErciQ1MsNv+FZ3k5bef0oi4ycLDnr2KC8hnmKil6CJouR/CHevtNL3JV8U5FD0A/Sphkb9KC9lG9AmwgKb+F/LB3V6Dfld5aRSBu+leWsWl6212dgiHdVzFJVrTUaP3hUtUP+sacoJP83Rt7W/ygj6Ws8e2ve27a3uPeeJkY96Fk5rrZAl/YgzazxAOUljUxVM9/bs9FscWvxN7+9iyEIpcWTEZwjQnwVWAB4v2X02qDEDW98ahWzKqkhyQFdUHI3tR3eSsXSwmkrheNTzYekHkNllo82kRi3nHpBTsBIcEZEGnL2JTrBx19MehCRZyjffRZa76/Zk+Kx89a4JgyhwkfC/3VmryzCJtQFbbMVVsgJTQwfEU41JppxMzhARv7Ll3nqUONErqB/GxDxuwipF5YT6RVG4dqJlDPDx35p81dIqkYUtSfN22NZlfLYiUkgwmAL01eWvLJ87Jea3Q5ENrdDGIf6ZYJrFDwP9IH X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SEZPR06MB5576.apcprd06.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(52116014)(376014)(22082099003)(18002099003)(11063799003)(3023799003)(56012099003)(38350700014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?rjRBTXDpDMNNfwKEKWicSVs++48EwcWKCN6K2EXvZLZ8M2jBkwdySATXV21E?= =?us-ascii?Q?Nb3nbtCprVNQH4byiXoP7lf63BnJo2PQBwyJrJdDGchMV3dQUhpXrx12lS7J?= =?us-ascii?Q?zH0MNyBa3D9zY4dgbnohUk98BttWIR+J+WzYA84xfcVZG/RbZaNtvd/lI2cV?= =?us-ascii?Q?2fwkx3h+dKmzTjRmy/pr8UhpGhH/TPbQXAIjZQlDF+7CWO3fs0QsvzSlvD6v?= =?us-ascii?Q?OsGaYIzCzMtQtgvSRbQqviPZ2Nv8w0QKY+lzmEhyqN5h1sWXGmpkrRAQh+lF?= =?us-ascii?Q?JBcpRl/LvwRHBMo3RB/S6plrIJTowTNQqrjF7o6zoWcgZmXPRkbBCGwTIKBL?= =?us-ascii?Q?EJ5rXGJl0IPDr2OsNrEW8ZdsHhbscXraPtcJoBkpKq3QmoHiCtBAqscUi1B2?= =?us-ascii?Q?oHf+A+hBJT+FDWo+/ccr++FJ7jw9WI/LasRjASSzEeBvg6zo9T/z/umoygBU?= =?us-ascii?Q?5U/Oh3yzfTGI61h9dpQHVFN4VOLd2n9LRUPnakFor9M1eJe8h4L+GIjwDFtK?= =?us-ascii?Q?RbO8ovdlkjBjZefcV0Gs2APDtbw+u2xhJZmhHGMfhETfrpGqR7EDcl8tzUfn?= =?us-ascii?Q?Q4ZRAYoju29PWzL3gKl3ImKlzXGzs64qRcIjNWL22rr5u1bnzFh0BH8KDIeD?= =?us-ascii?Q?6FseXJUmaO3DKM5Ir3yYLwzbjRslcN3VDJ59+rHaFAYpB+h/uhREzZiesjmp?= =?us-ascii?Q?c3dPk8iDozENpl+zwL8HzU1H5CycV/nmHpei++WMrD08Tx1PljoexP9bwpIz?= =?us-ascii?Q?LFN4x+cAyLpfl0K6ubE7IRAhQMP+47/GfTi0LD3hxkLuofKN1kjYjTblPRjn?= =?us-ascii?Q?4tMHdjHytkC3KWEdW3TQQSqGCMBeYvyqmfZwlX4LdZel66bW6Q4YAyMThS+e?= =?us-ascii?Q?xVoay1r0Cu7pZgWmbhbpoguLZp2f3a9dQIKpunv3//SJVte3i8JS4pRpnBlB?= =?us-ascii?Q?f7phHomijgWpzNGrKSXKk2k0hzC56YPrUyUzLqrarkRwiHowxZbQV4nP3Fbu?= =?us-ascii?Q?vpPCO1d3hnWEoOdt+ml+jWHYmBpfKefmdjwnLdSg5iOE/MtozSC3MqGjgnYW?= =?us-ascii?Q?RhlqOXOj3wLBG2tiiD6onKSc19CitKtMrpfqlfc7layY+C1p1OEQRv6/hxae?= =?us-ascii?Q?IcHpsTATt7T6zEuAUA2IIZ/C6XSwRhdz2WWrHDzPzz0VcdRvaDziW8Bb7oKq?= =?us-ascii?Q?2Ci590V4X+BcCr0J+GiBM2v/EgkG9DkNX3QsfVTDcs4tXAN+7Pts1gl9TmFI?= =?us-ascii?Q?hR1Q6jwvjk7fmhtsk0fEV3Yo+7dOkbv0E3Dpru+BIb74pEZplmwyhOnAOQ+F?= =?us-ascii?Q?XUutSOgj2WEhZ+jQdqVeyEf06nrihrWsDPEkE1AXxlbWi4fnnqslHBXCw9Di?= =?us-ascii?Q?iD1+vKwxODxfmBe/r3WIy0sJV6R4dm4zy8gfNqLJCvdKG400OncnVKqLfEXJ?= =?us-ascii?Q?X/tg+eOylztFWKs06BuAdSOW5aLFSsVdzrVDlhHt+dM92x2U3R4v9TYfGiuc?= =?us-ascii?Q?7aBCFiNarxlx1bYudxrowawLU0nojyNu+nGkeaTE6NGeJCTGdfGSF3FuvPlK?= =?us-ascii?Q?KbVDSqtanYrq9tmlL9yoajoSX65cf2S6OExIrJI2BMX5NB/qFxVPaL2VImx7?= =?us-ascii?Q?MzJ4ErEOlVS0bDvTmGVbmw3O/d6ykeX+vqLDo1WyEDeYGQYoPn10puJjctj4?= =?us-ascii?Q?7Pqn5DoRvqTxm5Kq7CcqO5yxbZMAQrNUyz5CjgeJ/9IHRfx31/DPTCnDl2DY?= =?us-ascii?Q?ylc7uYb2eQ=3D=3D?= X-OriginatorOrg: vivo.com X-MS-Exchange-CrossTenant-Network-Message-Id: 59d7c160-7e2e-4e18-04d3-08deb0d71200 X-MS-Exchange-CrossTenant-AuthSource: SEZPR06MB5576.apcprd06.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 May 2026 10:04:50.4029 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 923e42dc-48d5-4cbe-b582-1a797a6412ed X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: gXMEiio67Wshs6j32XzqI62fYGhRAKFuzW3SPG1Y+LVnDqvh2kCM7mnBLex8bblB1aJnBD1ZDppUtI+cPTgFUQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: KL1PR06MB5884 Content-Type: text/plain; charset="utf-8" From: Liao Yuanhong F2FS normally disables inline data for encrypted regular files because inline data is stored in the inode block and does not pass through the regular fscrypt data I/O path. This wastes space for small encrypted files on filesystems that otherwise use inline_data, including devices that enable blk-crypto for encrypted file contents. Add encrypted inline data support for encrypted regular files. Inline payloads are decrypted into page-cache plaintext on read and encrypted before being copied back into the inode block. The inline read path decrypts the inode payload through a temporary page. The inline write path encrypts page-cache plaintext before storing it back into the inode block. Update the inline-data size checks to use the encrypted inline capacity, since the stored payload is rounded to the fscrypt contents alignment. If an encrypted inline-data file is truncated from a non-zero offset, convert it to normal data blocks first and then use the normal truncate path. Only the inline payload is encrypted in software. These files are small enough to remain in the inode block, so the performance difference between hardware and software crypto is expected to be small compared to the space saved by retaining inline data. Signed-off-by: Liao Yuanhong --- fs/f2fs/Kconfig | 14 ++++++ fs/f2fs/data.c | 8 ++-- fs/f2fs/f2fs.h | 37 ++++++++++++++- fs/f2fs/file.c | 24 +++++++++- fs/f2fs/inline.c | 119 +++++++++++++++++++++++++++++++++++++++++------ fs/f2fs/super.c | 12 +++++ fs/f2fs/sysfs.c | 8 ++++ 7 files changed, 202 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig index 5916a02fb46d..9e31923b8df8 100644 --- a/fs/f2fs/Kconfig +++ b/fs/f2fs/Kconfig @@ -92,6 +92,20 @@ config F2FS_FAULT_INJECTION =20 If unsure, say N. =20 +config F2FS_FS_ENCRYPTED_INLINE_DATA + bool "F2FS encrypted inline data support" + depends on F2FS_FS && FS_ENCRYPTION_INLINE_CRYPT + help + Allow encrypted regular files to keep inline data inside the inode + while encrypting that inode-managed payload in software. + + This does not change normal data block encryption. Normal data + blocks continue to use the existing fscrypt path, such as blk-crypto + when inline encryption is enabled. + + Filesystems carrying the encrypted_inline_data incompat feature + require this option in order to be mounted correctly. + config F2FS_FS_COMPRESSION bool "F2FS compression feature" depends on F2FS_FS diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 657fd5986c73..9371ffa7c96d 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3700,7 +3700,7 @@ static int prepare_write_begin(struct f2fs_sb_info *s= bi, =20 /* f2fs_lock_op avoids race between write CP and convert_inline_page */ if (f2fs_has_inline_data(inode)) { - if (pos + len > MAX_INLINE_DATA(inode)) + if (pos + len > f2fs_max_inline_data(inode)) flag =3D F2FS_GET_BLOCK_DEFAULT; f2fs_map_lock(sbi, &lc, flag); locked =3D true; @@ -3720,8 +3720,10 @@ static int prepare_write_begin(struct f2fs_sb_info *= sbi, set_new_dnode(&dn, inode, ifolio, ifolio, 0); =20 if (f2fs_has_inline_data(inode)) { - if (pos + len <=3D MAX_INLINE_DATA(inode)) { - f2fs_do_read_inline_data(folio, ifolio); + if (pos + len <=3D f2fs_max_inline_data(inode)) { + err =3D f2fs_do_read_inline_data(folio, ifolio); + if (err) + goto out; set_inode_flag(inode, FI_DATA_EXIST); if (inode->i_nlink) folio_set_f2fs_inline(ifolio); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 832b2f8beb11..0a2d75baf23e 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -276,6 +276,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_RO 0x00004000 #define F2FS_FEATURE_DEVICE_ALIAS 0x00008000 #define F2FS_FEATURE_PACKED_SSA 0x00010000 +#define F2FS_FEATURE_ENCRYPTED_INLINE_DATA 0x00020000 =20 #define __F2FS_HAS_FEATURE(raw_super, mask) \ ((raw_super->feature & cpu_to_le32(mask)) !=3D 0) @@ -4502,7 +4503,7 @@ extern struct kmem_cache *f2fs_inode_entry_slab; bool f2fs_may_inline_data(struct inode *inode); bool f2fs_sanity_check_inline_data(struct inode *inode, struct folio *ifol= io); bool f2fs_may_inline_dentry(struct inode *inode); -void f2fs_do_read_inline_data(struct folio *folio, struct folio *ifolio); +int f2fs_do_read_inline_data(struct folio *folio, struct folio *ifolio); void f2fs_truncate_inline_inode(struct inode *inode, struct folio *ifolio, u64 from); int f2fs_read_inline_data(struct inode *inode, struct folio *folio); @@ -4595,6 +4596,39 @@ static inline bool f2fs_encrypted_file(struct inode = *inode) return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); } =20 +static inline bool f2fs_sb_has_encrypted_inline_data(struct f2fs_sb_info *= sbi); + +static inline bool f2fs_uses_encrypted_inline_data(struct inode *inode) +{ +#ifdef CONFIG_F2FS_FS_ENCRYPTED_INLINE_DATA + /* + * When the filesystem allows encrypted inline data, inline payloads + * in encrypted regular files are interpreted as ciphertext. + */ + return f2fs_sb_has_encrypted_inline_data(F2FS_I_SB(inode)) && + f2fs_encrypted_file(inode); +#else + return false; +#endif +} + +static inline unsigned int f2fs_max_inline_data(struct inode *inode) +{ + unsigned int max_bytes =3D MAX_INLINE_DATA(inode); + + /* + * Encrypted inline data is rounded up to the fscrypt contents + * alignment before being stored back into the inode. This is an + * on-disk layout constraint, so it must not depend on whether the + * inode's key has been prepared yet. + */ +#ifdef CONFIG_F2FS_FS_ENCRYPTED_INLINE_DATA + if (f2fs_uses_encrypted_inline_data(inode)) + max_bytes =3D round_down(max_bytes, FSCRYPT_CONTENTS_ALIGNMENT); +#endif + return max_bytes; +} + static inline void f2fs_set_encrypted_inode(struct inode *inode) { #ifdef CONFIG_FS_ENCRYPTION @@ -4827,6 +4861,7 @@ F2FS_FEATURE_FUNCS(compression, COMPRESSION); F2FS_FEATURE_FUNCS(readonly, RO); F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS); F2FS_FEATURE_FUNCS(packed_ssa, PACKED_SSA); +F2FS_FEATURE_FUNCS(encrypted_inline_data, ENCRYPTED_INLINE_DATA); =20 #ifdef CONFIG_BLK_DEV_ZONED static inline bool f2fs_zone_is_seq(struct f2fs_sb_info *sbi, int devi, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 71385ca4163d..ec243bb9039b 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -825,12 +825,32 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 = from, bool lock) } =20 if (f2fs_has_inline_data(inode)) { + if (f2fs_uses_encrypted_inline_data(inode) && from) { + f2fs_folio_put(ifolio, true); + if (lock) + f2fs_unlock_op(sbi, &lc); + + err =3D f2fs_convert_inline_inode(inode); + + if (lock) + f2fs_lock_op(sbi, &lc); + if (err) + goto out; + + ifolio =3D f2fs_get_inode_folio(sbi, inode->i_ino); + if (IS_ERR(ifolio)) { + err =3D PTR_ERR(ifolio); + goto out; + } + goto truncate_blocks; + } f2fs_truncate_inline_inode(inode, ifolio, from); f2fs_folio_put(ifolio, true); truncate_page =3D true; goto out; } =20 +truncate_blocks: set_new_dnode(&dn, inode, ifolio, NULL, 0); err =3D f2fs_get_dnode_of_data(&dn, free_from, LOOKUP_NODE_RA); if (err) { @@ -1147,7 +1167,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dent= ry *dentry, if (attr->ia_valid & ATTR_SIZE) { loff_t old_size =3D i_size_read(inode); =20 - if (attr->ia_size > MAX_INLINE_DATA(inode)) { + if (attr->ia_size > f2fs_max_inline_data(inode)) { /* * should convert inline inode before i_size_write to * keep smaller than inline_data size with inline flag. @@ -5007,7 +5027,7 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb= , struct iov_iter *iter, =20 if (f2fs_has_inline_data(inode)) { /* If the data will fit inline, don't bother. */ - if (pos + count <=3D MAX_INLINE_DATA(inode)) + if (pos + count <=3D f2fs_max_inline_data(inode)) return 0; ret =3D f2fs_convert_inline_inode(inode); if (ret) diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 099f72089701..6bcf103584ce 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -21,7 +21,7 @@ static bool support_inline_data(struct inode *inode) return false; if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) return false; - if (i_size_read(inode) > MAX_INLINE_DATA(inode)) + if (i_size_read(inode) > f2fs_max_inline_data(inode)) return false; return true; } @@ -31,6 +31,9 @@ bool f2fs_may_inline_data(struct inode *inode) if (!support_inline_data(inode)) return false; =20 + if (f2fs_uses_encrypted_inline_data(inode)) + return fscrypt_inode_supports_data_unit_inplace(inode); + return !f2fs_post_read_required(inode); } =20 @@ -65,7 +68,9 @@ bool f2fs_sanity_check_inline_data(struct inode *inode, s= truct folio *ifolio) * been synchronized to inmem fields. */ return (S_ISREG(inode->i_mode) && - (file_is_encrypt(inode) || file_is_verity(inode) || + ((file_is_encrypt(inode) && + !f2fs_sb_has_encrypted_inline_data(F2FS_I_SB(inode))) || + file_is_verity(inode) || (F2FS_I(inode)->i_flags & F2FS_COMPR_FL))); } =20 @@ -80,22 +85,60 @@ bool f2fs_may_inline_dentry(struct inode *inode) return true; } =20 -void f2fs_do_read_inline_data(struct folio *folio, struct folio *ifolio) +int f2fs_do_read_inline_data(struct folio *folio, struct folio *ifolio) { struct inode *inode =3D folio->mapping->host; + unsigned int len =3D min_t(loff_t, i_size_read(inode), + f2fs_max_inline_data(inode)); =20 if (folio_test_uptodate(folio)) - return; + return 0; =20 f2fs_bug_on(F2FS_I_SB(inode), folio->index); =20 - folio_zero_segment(folio, MAX_INLINE_DATA(inode), folio_size(folio)); + if (f2fs_uses_encrypted_inline_data(inode)) { + struct page *tmp_page; + void *kaddr; + int err; + + folio_zero_segment(folio, 0, folio_size(folio)); =20 - /* Copy the whole inline data block */ - memcpy_to_folio(folio, 0, inline_data_addr(inode, ifolio), - MAX_INLINE_DATA(inode)); + /* + * Decrypt through a temporary page because inline data occupies + * only a byte range inside the inode folio. + */ + tmp_page =3D alloc_page(GFP_NOFS | __GFP_ZERO); + if (!tmp_page) + return -ENOMEM; + + len =3D round_up(len, FSCRYPT_CONTENTS_ALIGNMENT); + if (len) { + memcpy_to_page(tmp_page, 0, inline_data_addr(inode, ifolio), + len); + err =3D fscrypt_decrypt_data_unit_inplace(inode, tmp_page, + len, 0, 0); + if (err) { + __free_page(tmp_page); + return err; + } + } + + kaddr =3D kmap_local_page(tmp_page); + memcpy_to_folio(folio, 0, kaddr, + min_t(loff_t, i_size_read(inode), + f2fs_max_inline_data(inode))); + kunmap_local(kaddr); + __free_page(tmp_page); + } else { + folio_zero_segment(folio, MAX_INLINE_DATA(inode), + folio_size(folio)); + /* Copy the whole inline data block */ + memcpy_to_folio(folio, 0, inline_data_addr(inode, ifolio), + MAX_INLINE_DATA(inode)); + } if (!folio_test_uptodate(folio)) folio_mark_uptodate(folio); + return 0; } =20 void f2fs_truncate_inline_inode(struct inode *inode, struct folio *ifolio, @@ -119,6 +162,7 @@ void f2fs_truncate_inline_inode(struct inode *inode, st= ruct folio *ifolio, int f2fs_read_inline_data(struct inode *inode, struct folio *folio) { struct folio *ifolio; + int ret =3D 0; =20 ifolio =3D f2fs_get_inode_folio(F2FS_I_SB(inode), inode->i_ino); if (IS_ERR(ifolio)) { @@ -134,7 +178,13 @@ int f2fs_read_inline_data(struct inode *inode, struct = folio *folio) if (folio->index) folio_zero_segment(folio, 0, folio_size(folio)); else - f2fs_do_read_inline_data(folio, ifolio); + ret =3D f2fs_do_read_inline_data(folio, ifolio); + + if (!folio->index && ret) { + f2fs_folio_put(ifolio, true); + folio_unlock(folio); + return ret; + } =20 if (!folio_test_uptodate(folio)) folio_mark_uptodate(folio); @@ -186,7 +236,9 @@ int f2fs_convert_inline_folio(struct dnode_of_data *dn,= struct folio *folio) =20 f2fs_bug_on(F2FS_F_SB(folio), folio_test_writeback(folio)); =20 - f2fs_do_read_inline_data(folio, dn->inode_folio); + err =3D f2fs_do_read_inline_data(folio, dn->inode_folio); + if (err) + return err; folio_mark_dirty(folio); =20 /* clear dirty state */ @@ -267,6 +319,8 @@ int f2fs_write_inline_data(struct inode *inode, struct = folio *folio) { struct f2fs_sb_info *sbi =3D F2FS_I_SB(inode); struct folio *ifolio; + void *inline_addr; + int err =3D 0; =20 ifolio =3D f2fs_get_inode_folio(sbi, inode->i_ino); if (IS_ERR(ifolio)) @@ -280,8 +334,44 @@ int f2fs_write_inline_data(struct inode *inode, struct= folio *folio) f2fs_bug_on(F2FS_I_SB(inode), folio->index); =20 f2fs_folio_wait_writeback(ifolio, NODE, true, true); - memcpy_from_folio(inline_data_addr(inode, ifolio), - folio, 0, MAX_INLINE_DATA(inode)); + inline_addr =3D inline_data_addr(inode, ifolio); + + if (f2fs_uses_encrypted_inline_data(inode)) { + struct page *tmp_page; + void *kaddr; + unsigned int len =3D min_t(loff_t, i_size_read(inode), + f2fs_max_inline_data(inode)); + + tmp_page =3D alloc_page(GFP_NOFS | __GFP_ZERO); + if (!tmp_page) { + err =3D -ENOMEM; + goto out; + } + + len =3D round_up(len, FSCRYPT_CONTENTS_ALIGNMENT); + if (len) { + kaddr =3D kmap_local_page(tmp_page); + memcpy_from_folio(kaddr, folio, 0, + min_t(loff_t, i_size_read(inode), + f2fs_max_inline_data(inode))); + kunmap_local(kaddr); + err =3D fscrypt_encrypt_data_unit_inplace(inode, tmp_page, + len, 0, 0); + } + if (!err) { + memset(inline_addr, 0, MAX_INLINE_DATA(inode)); + if (len) { + kaddr =3D kmap_local_page(tmp_page); + memcpy(inline_addr, kaddr, len); + kunmap_local(kaddr); + } + } + __free_page(tmp_page); + if (err) + goto out; + } else { + memcpy_from_folio(inline_addr, folio, 0, MAX_INLINE_DATA(inode)); + } folio_mark_dirty(ifolio); =20 f2fs_clear_page_cache_dirty_tag(folio); @@ -290,8 +380,9 @@ int f2fs_write_inline_data(struct inode *inode, struct = folio *folio) set_inode_flag(inode, FI_DATA_EXIST); =20 folio_clear_f2fs_inline(ifolio); +out: f2fs_folio_put(ifolio, true); - return 0; + return err; } =20 int f2fs_recover_inline_data(struct inode *inode, struct folio *nfolio) @@ -826,7 +917,7 @@ int f2fs_inline_data_fiemap(struct inode *inode, return PTR_ERR(ifolio); f2fs_folio_wait_writeback(ifolio, NODE, true, true); } - ilen =3D min_t(size_t, MAX_INLINE_DATA(inode), i_size_read(inode)); + ilen =3D min_t(size_t, f2fs_max_inline_data(inode), i_size_read(inode)); if (start >=3D ilen) goto out; if (start + len < ilen) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index c6afdbd6e1cd..9eddcde7939c 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1549,6 +1549,18 @@ static int f2fs_check_opt_consistency(struct fs_cont= ext *fc, return -EINVAL; } =20 + if (f2fs_sb_has_encrypted_inline_data(sbi)) { + if (!IS_ENABLED(CONFIG_F2FS_FS_ENCRYPTED_INLINE_DATA)) { + f2fs_err(sbi, + "encrypted_inline_data requires CONFIG_F2FS_FS_ENCRYPTED_INLINE_DATA"= ); + return -EINVAL; + } + if (!f2fs_sb_has_encrypt(sbi)) { + f2fs_err(sbi, "encrypted inline_data requires encryption feature"); + return -EINVAL; + } + } + /* * The BLKZONED feature indicates that the drive was formatted with * zone alignment optimization. This is optional for host-aware diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 665687244c93..600eaee75926 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -1399,6 +1399,9 @@ F2FS_FEATURE_RO_ATTR(pin_file); F2FS_FEATURE_RO_ATTR(linear_lookup); #endif F2FS_FEATURE_RO_ATTR(packed_ssa); +#ifdef CONFIG_F2FS_FS_ENCRYPTED_INLINE_DATA +F2FS_FEATURE_RO_ATTR(encrypted_inline_data); +#endif F2FS_FEATURE_RO_ATTR(fserror); =20 #define ATTR_LIST(name) (&f2fs_attr_##name.attr) @@ -1567,6 +1570,9 @@ static struct attribute *f2fs_feat_attrs[] =3D { BASE_ATTR_LIST(linear_lookup), #endif BASE_ATTR_LIST(packed_ssa), +#ifdef CONFIG_F2FS_FS_ENCRYPTED_INLINE_DATA + BASE_ATTR_LIST(encrypted_inline_data), +#endif BASE_ATTR_LIST(fserror), NULL, }; @@ -1604,6 +1610,7 @@ F2FS_SB_FEATURE_RO_ATTR(compression, COMPRESSION); F2FS_SB_FEATURE_RO_ATTR(readonly, RO); F2FS_SB_FEATURE_RO_ATTR(device_alias, DEVICE_ALIAS); F2FS_SB_FEATURE_RO_ATTR(packed_ssa, PACKED_SSA); +F2FS_SB_FEATURE_RO_ATTR(encrypted_inline_data, ENCRYPTED_INLINE_DATA); =20 static struct attribute *f2fs_sb_feat_attrs[] =3D { ATTR_LIST(sb_encryption), @@ -1622,6 +1629,7 @@ static struct attribute *f2fs_sb_feat_attrs[] =3D { ATTR_LIST(sb_readonly), ATTR_LIST(sb_device_alias), ATTR_LIST(sb_packed_ssa), + ATTR_LIST(sb_encrypted_inline_data), NULL, }; ATTRIBUTE_GROUPS(f2fs_sb_feat); --=20 2.34.1 From nobody Fri Jun 12 18:37:52 2026 Received: from OS8PR02CU002.outbound.protection.outlook.com (mail-japanwestazon11012063.outbound.protection.outlook.com [40.107.75.63]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E33C538E8B0; Wed, 13 May 2026 10:04:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.75.63 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778666700; cv=fail; b=NmDyhjHLowzpFb6ibfeNhIQU8TQGf6lmJOOV3p1bcQk0rE0yJel+dGH/+cf4ToSLTWReBSVa0Qw//bcU9dJUudROud0U/dJ4GYIY19nzV8rH258GAcSNwEA2Me/BMrMw3X8f/KcC+uABo52H3CSCMwOlTgVScUKOwRYs24pjWGw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778666700; c=relaxed/simple; bh=/F5DKzJR0e91a6Mw9HiUd48arqAO8kVHMUU88TSq8LM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=KVnsYQu0cPuBkrk1l1N3J8OGGjbhf9HBDAu++eQFvLuplHdau+GFPzRybYa9Ci2lNw+Lx05fM5xBs+uhqdwwzQykBmUThUjinwOIZ79nqHN+PN5u9SeRsXq9N7jSnNrA0eaGPoxqTe3sVqTSs6cDXeygS/RrKpHpsArQO5iwJDE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=vivo.com; spf=pass smtp.mailfrom=vivo.com; dkim=pass (2048-bit key) header.d=vivo.com header.i=@vivo.com header.b=h2gZH/xZ; arc=fail smtp.client-ip=40.107.75.63 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=vivo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=vivo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=vivo.com header.i=@vivo.com header.b="h2gZH/xZ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=YGs76JUK8sE5hOU3CnCwWgqcbJZy9yb+0pQVvb3NDPwfWiwufsyCjZ3ixMT0WvDIVHzzpp5WOp9l0TgzjHH37i12HAI8/4QEjuPdi/J2VGbc7AXwLe0CGZAYIegT1qUFrrdcthhPG2ZO6klsbNss7bf4LTGkG1NT6+t5uGxKunUBufBK1/raGEIU1ut34MA5GA1sNn9C45sAUohGw2yaKvA2zJg+XtgH5Q8vRelAnGl98ggtB3rJ5TLi/21Be7vD8SPwsyEqXiOxLOGBgNxCPM/a+heM5BX3NlwnQHbV6UhjzLoBZrvwCC00b5CGDTSI6oupg/JALaA6qq0icg0sjA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=zihDLH9cXne2s1Uy6IVFERErv70lE3luW+XJUdZQU/c=; b=a1XcgbGciM/azyVbaSr80jFxldLDJ7ktxJlWZZUbS3gGg2SUdfS71Kzke8DHO6KODOEYD1/VrTAjfK7uI0wCfO1UJJF/Kn58019Y6xhcGcQV4Fyja5ekGuwSr83EF+5cWFY/A8qh2FUh/77JiwInkhsid0wycYfuDX1cpdlp4ecb2Li66vZLyKq8MNPdLfJifwy9Gpq+nHf/WqMxtHYAcGGMMvARJvgxUVIRqpxHfn7toaEsgroRov1Hc9HoJ2eVBkxTbh0rTMgIyjWhJbI87N6CHIGjzGjvRwsyYNwTOju7Fkk2mQ5gQVT05CSubFj9FhhnJEZTz6hWmw4Ps/ej6Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=vivo.com; dmarc=pass action=none header.from=vivo.com; dkim=pass header.d=vivo.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vivo.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=zihDLH9cXne2s1Uy6IVFERErv70lE3luW+XJUdZQU/c=; b=h2gZH/xZeLQ9j45kN5OndovD1vohmho+tDpzBnOkz2iZwOKpSAcBgXF+xgV+O8GfbgFxMf2GS+3DNuoklYwDEezojxTGhYqhi8hJhToU1YmEWbJyUgqyIIiNGsG5QfzHw3mSvl5ysHvqPGkzfQVcXpKar3mR58lSBUtRUPMRpA/xUAliJ0mnYSXNZNbh8O32kAfjn5F/wA4Lh60CQiBUJfwJqtNkFemDhsUmw+f5iXXMlMlAjT2jqtA9MnEukoIWvLuNn+0OY2MRAOOkmesCdTpgaN/k4ZGVjPZIePvccfU6UMacsq+fYrbSbwqQO3WiGefEwF8xs5k6kJq0tS2gsQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=vivo.com; Received: from SEZPR06MB5576.apcprd06.prod.outlook.com (2603:1096:101:c9::14) by KL1PR06MB5884.apcprd06.prod.outlook.com (2603:1096:820:dd::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9913.11; Wed, 13 May 2026 10:04:53 +0000 Received: from SEZPR06MB5576.apcprd06.prod.outlook.com ([fe80::24bc:5613:3ffa:cb96]) by SEZPR06MB5576.apcprd06.prod.outlook.com ([fe80::24bc:5613:3ffa:cb96%6]) with mapi id 15.20.9913.009; Wed, 13 May 2026 10:04:53 +0000 From: LiaoYuanhong-vivo To: Jaegeuk Kim , Chao Yu , Jonathan Corbet , Shuah Khan , linux-f2fs-devel@lists.sourceforge.net (open list:F2FS FILE SYSTEM), linux-kernel@vger.kernel.org (open list), linux-doc@vger.kernel.org (open list:DOCUMENTATION) Cc: Liao Yuanhong Subject: [PATCH 3/3] Documentation: f2fs: document encrypted inline data Date: Wed, 13 May 2026 18:04:30 +0800 Message-Id: <20260513100431.299904-4-liaoyuanhong@vivo.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260513100431.299904-1-liaoyuanhong@vivo.com> References: <20260513100431.299904-1-liaoyuanhong@vivo.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TP0P295CA0031.TWNP295.PROD.OUTLOOK.COM (2603:1096:910:4::12) To SEZPR06MB5576.apcprd06.prod.outlook.com (2603:1096:101:c9::14) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SEZPR06MB5576:EE_|KL1PR06MB5884:EE_ X-MS-Office365-Filtering-Correlation-Id: f34a766c-db3d-4e23-e2aa-08deb0d713ec X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|52116014|376014|22082099003|18002099003|11063799003|3023799003|56012099003|38350700014; X-Microsoft-Antispam-Message-Info: N+ncZ3OX3e/DI4ivZamos4sGwuO4yW4cOz8qmkpONdta+ae/E6GBEFNRdUeBzkPshExHPlyhPmGMJ5CbpRizwl2xcikkudMbKsd/IurhHWDzzeD8rioQeP4tn6QfX1LOVUJlTajtBzCMz+h5LYFBCfl/vSydVSbdX5k+hXsACwDQubOoTmaUEMZDF57W4ypUqe/Qv5QspBjr4G+kdcrHMztZloVtY8Klj/PelOv/kSfU9qU/6dK6euOnNPm4XsPpcKgzo+7cuK1F/Hb61VpB4DL5uH6jHdZPlGgLokShjfaIyBerbrCvqVf2dBKUy0tG1XO6PZwW8JYFoBL74dBWY4dhKEJybmaHoUxyOPeh5QhwBpnNfaHfpF/WZQ0JSejDXdlzIYnTsUG4JxcVURBKXsVNMI4VnKA6GbFHL2TyaFNxmYkhhSJSeKSsqyAK6KL6i1giALi4eqoxofbSkipkrLLKh0ynUX5B7yV7FQtjkXK/Sce91gbat5sha2G/lnbVemhQtdwHi+BpvJPZMAtqARppibPjw0kcCvXk5+9UjcR/sHja7gPWSNO8Es0czht/MLpBX6RQhh3xLlKqze+4cjgPymr9QiDFGdYlszy0KziDBYhTv6VR1rFhbnJBQXq/6eMYAWWd/w6kiZ0QNuDeXhVJTUT6ChgM8aX6H7V1OalkK+vMdnZeVJQBGlgSroJnPJf4DlxCbtI76xCzztqyE1K2p6wkFEti+IFnJmfUIf14TaoDfPqjEIt5UdMU3nnA X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SEZPR06MB5576.apcprd06.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(52116014)(376014)(22082099003)(18002099003)(11063799003)(3023799003)(56012099003)(38350700014);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?OMwLQPhaWDMFEO7ti6SnR4cCijYYGs4CHhinNJB+5kYVfj5N2SY6BKyM1EJu?= =?us-ascii?Q?9e5g6vPncTHVKzr4UurybMF468LAWOL3WoIrkEWpIwM6IMLTvFe8bOKDzy0x?= =?us-ascii?Q?VPfk7pN4+0Dy0aqAdFEJspr7vt+rc3OLr2X0yDySMW7tgnl7c1LTXxQcOpbE?= =?us-ascii?Q?yyhzQVYNA04GSXgt7M3PiCPEXNwQcPVXaDWrC9GFCb70mjNcWNID39SXIXbm?= =?us-ascii?Q?PvSH0wvVvLplMWwy1umDxYzL5VTOI+KcLvEk1p+HtHrVkin4+nH7KbZPBnZs?= =?us-ascii?Q?CiicasPFR2Lx53l7+RZmKRd4Z5ZEk5i8PQ8eFvfuTB9ePRUyi4//+3xHat/S?= =?us-ascii?Q?7vdd9YSQ5NXt0i4jEujF/aIldcAcoI32q+KWeY0/uNp02BH31XojIpBACpGQ?= =?us-ascii?Q?H8HATL8r5plZly8971L4/8Z3PjmH4A1IaXQh0vjc3QUMaGhfIOHnA57HEFiT?= =?us-ascii?Q?8xftHeZz0RNqeXIb3vemYgLxxlxxN+H9AaLk0O4PgRpnuVetbyEuE1ncp/gV?= =?us-ascii?Q?1dsXt4uGnOyqRGF/SCP1L+tJ5Y77Crtuuuij9/h/jnzR8i/OXUT3oU+r3vGw?= =?us-ascii?Q?yACoxBJbzBzF5wRiV5Y0aHgxhGY3GnRxfsq6dOUI71iY81ME1bB8SnRvzCTJ?= =?us-ascii?Q?8L2YOpS8xkfkcZBKqYtwCh76rDNG/sqfoXDhqrSwvAb/pCqnHqpyeOHJTnQ+?= =?us-ascii?Q?OJsOpC7NqkDQxJkr5ja4fnAEBgB4BpdmjrKE+jeMo0WiX2mzpsP6tFchSxOP?= =?us-ascii?Q?gcJq0ngvYN4ox/ZqjUZFMWi17/TrHgtMaa8+lNYWH/OEHQDDN7+QAh6c7Id5?= =?us-ascii?Q?SzCaNbHK7eSb3NMDsJagLAuP/ZXH/gUKQXpfSRrd7k/qm7qe1KU8HoLGt1J1?= =?us-ascii?Q?mJmJJT4PjlFgwY9cYw8Mm6J8ELyqgdUEzeR/O8tG1Zie++ogmmqGWzxLBchM?= =?us-ascii?Q?6DyEF6FYMcu/p6h2bduunG+c9IGMVxyh5jQu4bpt6JqtJYXTzWHvFaSv7OrA?= =?us-ascii?Q?uGL0KyluNUGox70U1NkSeF0tPDv1vgMWsZKsUNG+etPETKYxAoQL9UaomGJU?= =?us-ascii?Q?/gSaFl+eOIi/OXukH5QXFjBdKgdrIFESvAcuL+aOQU4zucrkSkAxBk+OEB/8?= =?us-ascii?Q?9E+RMJb1+LEAxhuWfDBbLas4BAauK0fulOyB6ZVJJlK3e/CQ4oGbtTwPqzmW?= =?us-ascii?Q?PgYTlauk/prw65223UoKU7DPaE5KpSgjUNaaR0aa1fXDG1zv7Iwgrz92phJ5?= =?us-ascii?Q?8LRP+dfEDFw5Fz3FbN7IGudTVxI3/pNQc6GDouVL3JBlO6JjJ8+F6nkDxwpu?= =?us-ascii?Q?WZHElkXGA0UlKLkcvFjCj/VGJ2rNjmxxne2cY8FkKGgD5zH64bRyBMZxzBSp?= =?us-ascii?Q?I9cIXndB68ZNcrxvaNUwTjMY+GrwCW/C3kUxgbBVGqrgjGgkYOjNofzaHqrf?= =?us-ascii?Q?fTFhYIifWEdYEhkK9CpugdrFBr9UtkB/mHNPhMxknwMZvWDgZS8bAPmrBgMb?= =?us-ascii?Q?QjsXgDOWSZXfsAPOwM02JRpGKAGeJKBPkVDrsecdUWmUibkLCf4J4Er/t+0J?= =?us-ascii?Q?Ef37xlIFSWBjVOXhACwSBKF1V/HqkE8X/VS9G45KqmkPA1v7P/6B9sveHYHj?= =?us-ascii?Q?mYqwksM/UoGRAKzG1sLBd5qc0PnhsY67BzY4X13TklYLbB3QrpP8byl/T/nz?= =?us-ascii?Q?uoBTmtYXwuiXQC4Yo/P6Sxqd26qyVHry2a5XfHx/t6mYWHeikRwJcgd+ZKgf?= =?us-ascii?Q?u3orOZSUig=3D=3D?= X-OriginatorOrg: vivo.com X-MS-Exchange-CrossTenant-Network-Message-Id: f34a766c-db3d-4e23-e2aa-08deb0d713ec X-MS-Exchange-CrossTenant-AuthSource: SEZPR06MB5576.apcprd06.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 May 2026 10:04:53.4014 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 923e42dc-48d5-4cbe-b582-1a797a6412ed X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 7Xq28HCsQKw5dtIs4+fThb/kqcYzbsAsdmg0AvUiOPjzmCr41hngTVvwxww2P4x3zUMz3M0jSLv+qMbWMTUaMg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: KL1PR06MB5884 Content-Type: text/plain; charset="utf-8" From: Liao Yuanhong Document the F2FS encrypted_inline_data feature, including the on-disk feature requirement, the CONFIG_F2FS_FS_ENCRYPTED_INLINE_DATA dependency, how inline payloads are encrypted and decrypted, and the truncate behavior. Also list encrypted_inline_data in the supported F2FS feature sysfs documentation. Signed-off-by: Liao Yuanhong --- Documentation/ABI/testing/sysfs-fs-f2fs | 5 +++-- Documentation/filesystems/f2fs.rst | 27 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/te= sting/sysfs-fs-f2fs index 27d5e88facbe..dad483fb2fc1 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -258,7 +258,8 @@ Description: Expand /sys/fs/f2fs//features to mee= t sysfs rule. encryption, block_zoned (aka blkzoned), extra_attr, project_quota (aka projquota), inode_checksum, flexible_inline_xattr, quota_ino, inode_crtime, lost_found, - verity, sb_checksum, casefold, readonly, compression. + verity, sb_checksum, casefold, readonly, compression, + encrypted_inline_data. Note that, pin_file is moved into /sys/fs/f2fs/features/. =20 What: /sys/fs/f2fs/features/ @@ -271,7 +272,7 @@ Description: Shows all enabled kernel features. inode_crtime, lost_found, verity, sb_checksum, casefold, readonly, compression, test_dummy_encryption_v2, atomic_write, pin_file, encrypted_casefold, linear_lookup, - fserror. + fserror, encrypted_inline_data. =20 What: /sys/fs/f2fs//inject_rate Date: May 2016 diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems= /f2fs.rst index 5bc37a1c4e51..1f3e02352dd1 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -420,6 +420,33 @@ lookup_mode=3D%s Control the directory lookup behavi= or for casefolded =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 +Encrypted inline data +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +F2FS normally disables inline data for encrypted regular files, since inli= ne +data is stored inside the inode block and does not pass through the regular +block I/O path. When a filesystem is formatted with the encrypted_inline_= data +feature, encrypted regular files may keep small file contents in the inode +block. The inline payload is encrypted with fscrypt contents-key semantics +before it is written to the inode, and it is decrypted back to page-cache +plaintext when it is read. + +This feature requires the encrypt feature on disk and kernel support for +CONFIG_F2FS_FS_ENCRYPTED_INLINE_DATA. It is intended to be used together = with +the inline_data mount option. When the normal encrypted file contents pat= h uses +blk-crypto, fscrypt also prepares a software contents-key transform for the +filesystem-managed inline payload. + +Encrypted inline data is stored in fscrypt contents-aligned units. Theref= ore, +the maximum plaintext size that can stay inline may be slightly smaller th= an the +ordinary inline data capacity. If an encrypted inline-data file is trunca= ted +from a non-zero offset, F2FS first converts the inline payload to normal d= ata +blocks and then applies the truncate operation. + +Recovery copies inline payloads as on-disk bytes. Encryption and decrypti= on are +performed only when moving data between the inode inline area and page-cac= he +plaintext. + Debugfs Entries =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 --=20 2.34.1