Commit 7a0263dc authored by Eric Biggers's avatar Eric Biggers
Browse files

fscrypt: replace get_ino_and_lblk_bits with just has_32bit_inodes

Now that fs/crypto/ computes the filesystem's lblk_bits from its maximum
file size, it is no longer necessary for filesystems to provide
lblk_bits via fscrypt_operations::get_ino_and_lblk_bits.

It is still necessary for fs/crypto/ to retrieve ino_bits from the
filesystem.  However, this is used only to decide whether inode numbers
fit in 32 bits.  Also, ino_bits is static for all relevant filesystems,
i.e. it doesn't depend on the filesystem instance.

Therefore, in the interest of keeping things as simple as possible,
replace 'get_ino_and_lblk_bits' with a flag 'has_32bit_inodes'.  This
can always be changed back to a function if a filesystem needs it to be
dynamic, but for now a static flag is all that's needed.

Link: https://lore.kernel.org/r/20230925055451.59499-5-ebiggers@kernel.org


Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
parent f0904e8b
Loading
Loading
Loading
Loading
+15 −18
Original line number Diff line number Diff line
@@ -118,11 +118,11 @@ static bool supported_direct_key_modes(const struct inode *inode,
}

static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy,
					 const struct inode *inode,
					 const char *type, int max_ino_bits)
					 const struct inode *inode)
{
	const char *type = (policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64)
				? "IV_INO_LBLK_64" : "IV_INO_LBLK_32";
	struct super_block *sb = inode->i_sb;
	int ino_bits = 64, lblk_bits = 64;

	/*
	 * IV_INO_LBLK_* exist only because of hardware limitations, and
@@ -149,9 +149,15 @@ static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy,
			     type, sb->s_id);
		return false;
	}
	if (sb->s_cop->get_ino_and_lblk_bits)
		sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits);
	if (ino_bits > max_ino_bits) {

	/*
	 * IV_INO_LBLK_64 and IV_INO_LBLK_32 both require that inode numbers fit
	 * in 32 bits.  In principle, IV_INO_LBLK_32 could support longer inode
	 * numbers because it hashes the inode number; however, currently the
	 * inode number is gotten from inode::i_ino which is 'unsigned long'.
	 * So for now the implementation limit is 32 bits.
	 */
	if (!sb->s_cop->has_32bit_inodes) {
		fscrypt_warn(inode,
			     "Can't use %s policy on filesystem '%s' because its inode numbers are too long",
			     type, sb->s_id);
@@ -242,18 +248,9 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
					policy->filenames_encryption_mode))
		return false;

	if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) &&
	    !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_64", 32))
		return false;

	/*
	 * IV_INO_LBLK_32 hashes the inode number, so in principle it can
	 * support any ino_bits.  However, currently the inode number is gotten
	 * from inode::i_ino which is 'unsigned long'.  So for now the
	 * implementation limit is 32 bits.
	 */
	if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) &&
	    !supported_iv_ino_lblk_policy(policy, inode, "IV_INO_LBLK_32", 32))
	if ((policy->flags & (FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 |
			      FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) &&
	    !supported_iv_ino_lblk_policy(policy, inode))
		return false;

	if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) {
+1 −8
Original line number Diff line number Diff line
@@ -232,20 +232,13 @@ static bool ext4_has_stable_inodes(struct super_block *sb)
	return ext4_has_feature_stable_inodes(sb);
}

static void ext4_get_ino_and_lblk_bits(struct super_block *sb,
				       int *ino_bits_ret, int *lblk_bits_ret)
{
	*ino_bits_ret = 8 * sizeof(EXT4_SB(sb)->s_es->s_inodes_count);
	*lblk_bits_ret = 8 * sizeof(ext4_lblk_t);
}

const struct fscrypt_operations ext4_cryptops = {
	.needs_bounce_pages	= 1,
	.has_32bit_inodes	= 1,
	.legacy_key_prefix	= "ext4:",
	.get_context		= ext4_get_context,
	.set_context		= ext4_set_context,
	.get_dummy_policy	= ext4_get_dummy_policy,
	.empty_dir		= ext4_empty_dir,
	.has_stable_inodes	= ext4_has_stable_inodes,
	.get_ino_and_lblk_bits	= ext4_get_ino_and_lblk_bits,
};
+1 −8
Original line number Diff line number Diff line
@@ -3203,13 +3203,6 @@ static bool f2fs_has_stable_inodes(struct super_block *sb)
	return true;
}

static void f2fs_get_ino_and_lblk_bits(struct super_block *sb,
				       int *ino_bits_ret, int *lblk_bits_ret)
{
	*ino_bits_ret = 8 * sizeof(nid_t);
	*lblk_bits_ret = 8 * sizeof(block_t);
}

static struct block_device **f2fs_get_devices(struct super_block *sb,
					      unsigned int *num_devs)
{
@@ -3232,13 +3225,13 @@ static struct block_device **f2fs_get_devices(struct super_block *sb,

static const struct fscrypt_operations f2fs_cryptops = {
	.needs_bounce_pages	= 1,
	.has_32bit_inodes	= 1,
	.legacy_key_prefix	= "f2fs:",
	.get_context		= f2fs_get_context,
	.set_context		= f2fs_set_context,
	.get_dummy_policy	= f2fs_get_dummy_policy,
	.empty_dir		= f2fs_empty_dir,
	.has_stable_inodes	= f2fs_has_stable_inodes,
	.get_ino_and_lblk_bits	= f2fs_get_ino_and_lblk_bits,
	.get_devices		= f2fs_get_devices,
};
#endif
+11 −15
Original line number Diff line number Diff line
@@ -74,6 +74,17 @@ struct fscrypt_operations {
	 */
	unsigned int needs_bounce_pages : 1;

	/*
	 * If set, then fs/crypto/ will allow the use of encryption settings
	 * that assume inode numbers fit in 32 bits (i.e.
	 * FSCRYPT_POLICY_FLAG_IV_INO_LBLK_{32,64}), provided that the other
	 * prerequisites for these settings are also met.  This is only useful
	 * if the filesystem wants to support inline encryption hardware that is
	 * limited to 32-bit or 64-bit data unit numbers and where programming
	 * keyslots is very slow.
	 */
	unsigned int has_32bit_inodes : 1;

	/*
	 * This field exists only for backwards compatibility reasons and should
	 * only be set by the filesystems that are setting it already.  It
@@ -151,21 +162,6 @@ struct fscrypt_operations {
	 */
	bool (*has_stable_inodes)(struct super_block *sb);

	/*
	 * Get the number of bits that the filesystem uses to represent inode
	 * numbers and file logical block numbers.
	 *
	 * By default, both of these are assumed to be 64-bit.  This function
	 * can be implemented to declare that either or both of these numbers is
	 * shorter, which may allow the use of the
	 * FSCRYPT_POLICY_FLAG_IV_INO_LBLK_{32,64} flags and/or the use of
	 * inline crypto hardware whose maximum DUN length is less than 64 bits
	 * (e.g., eMMC v5.2 spec compliant hardware).  This function only needs
	 * to be implemented if support for one of these features is needed.
	 */
	void (*get_ino_and_lblk_bits)(struct super_block *sb,
				      int *ino_bits_ret, int *lblk_bits_ret);

	/*
	 * Return an array of pointers to the block devices to which the
	 * filesystem may write encrypted file contents, NULL if the filesystem