fscrypt: replace get_ino_and_lblk_bits with just has_32bit_inodes
authorEric Biggers <ebiggers@google.com>
Mon, 25 Sep 2023 05:54:50 +0000 (22:54 -0700)
committerEric Biggers <ebiggers@google.com>
Tue, 26 Sep 2023 05:34:33 +0000 (22:34 -0700)
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: Eric Biggers <ebiggers@google.com>
fs/crypto/policy.c
fs/ext4/crypto.c
fs/f2fs/super.c
include/linux/fscrypt.h

index 7b34949..32709da 100644 (file)
@@ -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))) {
index 5cd7bcf..9e36731 100644 (file)
@@ -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,
 };
index 55aa0ed..c449157 100644 (file)
@@ -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
index 4505078..09a3cac 100644 (file)
@@ -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