Merge tag 'x86_cache_for_6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
[linux-block.git] / block / blk-crypto.c
index 45378586151f78572d77c47be4d220c30c2995e8..4d760b092deb93ab678365fb6acb3464a5f6df35 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/blkdev.h>
 #include <linux/blk-crypto-profile.h>
 #include <linux/module.h>
+#include <linux/ratelimit.h>
 #include <linux/slab.h>
 
 #include "blk-crypto-internal.h"
@@ -224,27 +225,27 @@ static bool bio_crypt_check_alignment(struct bio *bio)
        return true;
 }
 
-blk_status_t __blk_crypto_init_request(struct request *rq)
+blk_status_t __blk_crypto_rq_get_keyslot(struct request *rq)
 {
        return blk_crypto_get_keyslot(rq->q->crypto_profile,
                                      rq->crypt_ctx->bc_key,
                                      &rq->crypt_keyslot);
 }
 
-/**
- * __blk_crypto_free_request - Uninitialize the crypto fields of a request.
- *
- * @rq: The request whose crypto fields to uninitialize.
- *
- * Completely uninitializes the crypto fields of a request. If a keyslot has
- * been programmed into some inline encryption hardware, that keyslot is
- * released. The rq->crypt_ctx is also freed.
- */
-void __blk_crypto_free_request(struct request *rq)
+void __blk_crypto_rq_put_keyslot(struct request *rq)
 {
        blk_crypto_put_keyslot(rq->crypt_keyslot);
+       rq->crypt_keyslot = NULL;
+}
+
+void __blk_crypto_free_request(struct request *rq)
+{
+       /* The keyslot, if one was needed, should have been released earlier. */
+       if (WARN_ON_ONCE(rq->crypt_keyslot))
+               __blk_crypto_rq_put_keyslot(rq);
+
        mempool_free(rq->crypt_ctx, bio_crypt_ctx_pool);
-       blk_crypto_rq_set_defaults(rq);
+       rq->crypt_ctx = NULL;
 }
 
 /**
@@ -399,30 +400,39 @@ int blk_crypto_start_using_key(struct block_device *bdev,
 }
 
 /**
- * blk_crypto_evict_key() - Evict a key from any inline encryption hardware
- *                         it may have been programmed into
- * @bdev: The block_device who's associated inline encryption hardware this key
- *     might have been programmed into
- * @key: The key to evict
+ * blk_crypto_evict_key() - Evict a blk_crypto_key from a block_device
+ * @bdev: a block_device on which I/O using the key may have been done
+ * @key: the key to evict
+ *
+ * For a given block_device, this function removes the given blk_crypto_key from
+ * the keyslot management structures and evicts it from any underlying hardware
+ * keyslot(s) or blk-crypto-fallback keyslot it may have been programmed into.
  *
- * Upper layers (filesystems) must call this function to ensure that a key is
- * evicted from any hardware that it might have been programmed into.  The key
- * must not be in use by any in-flight IO when this function is called.
+ * Upper layers must call this before freeing the blk_crypto_key.  It must be
+ * called for every block_device the key may have been used on.  The key must no
+ * longer be in use by any I/O when this function is called.
  *
- * Return: 0 on success or if the key wasn't in any keyslot; -errno on error.
+ * Context: May sleep.
  */
-int blk_crypto_evict_key(struct block_device *bdev,
-                        const struct blk_crypto_key *key)
+void blk_crypto_evict_key(struct block_device *bdev,
+                         const struct blk_crypto_key *key)
 {
        struct request_queue *q = bdev_get_queue(bdev);
+       int err;
 
        if (blk_crypto_config_supported_natively(bdev, &key->crypto_cfg))
-               return __blk_crypto_evict_key(q->crypto_profile, key);
-
+               err = __blk_crypto_evict_key(q->crypto_profile, key);
+       else
+               err = blk_crypto_fallback_evict_key(key);
        /*
-        * If the block_device didn't support the key, then blk-crypto-fallback
-        * may have been used, so try to evict the key from blk-crypto-fallback.
+        * An error can only occur here if the key failed to be evicted from a
+        * keyslot (due to a hardware or driver issue) or is allegedly still in
+        * use by I/O (due to a kernel bug).  Even in these cases, the key is
+        * still unlinked from the keyslot management structures, and the caller
+        * is allowed and expected to free it right away.  There's nothing
+        * callers can do to handle errors, so just log them and return void.
         */
-       return blk_crypto_fallback_evict_key(key);
+       if (err)
+               pr_warn_ratelimited("%pg: error %d evicting key\n", bdev, err);
 }
 EXPORT_SYMBOL_GPL(blk_crypto_evict_key);