On 5/6/19 3:35 PM, Satya Tangirala wrote:
> +#ifdef CONFIG_BLK_CRYPT_CTX
> +static inline void bio_crypt_advance(struct bio *bio, unsigned int bytes)
> +{
> +     if (bio_is_encrypted(bio)) {
> +             bio->bi_crypt_context.data_unit_num +=
> +                     bytes >> bio->bi_crypt_context.data_unit_size_bits;
> +     }
> +}
> +
> +void bio_clone_crypt_context(struct bio *dst, struct bio *src)
> +{
> +     if (bio_crypt_swhandled(src))
> +             return;
> +     dst->bi_crypt_context = src->bi_crypt_context;
> +
> +     if (!bio_crypt_has_keyslot(src))
> +             return;
> +
> +     /**

Please use "/*" to start comment blocks other than kernel-doc headers.

> +      * This should always succeed because the src bio should already
> +      * have a reference to the keyslot.
> +      */
> +     BUG_ON(!keyslot_manager_get_slot(src->bi_crypt_context.processing_ksm,
> +                                       src->bi_crypt_context.keyslot));

Are you aware that using BUG_ON() if there is a reasonable way to
recover is not acceptable?

> +}
> +
> +bool bio_crypt_should_process(struct bio *bio, struct request_queue *q)
> +{
> +     if (!bio_is_encrypted(bio))
> +             return false;
> +
> +     WARN_ON(!bio_crypt_has_keyslot(bio));
> +     return q->ksm == bio->bi_crypt_context.processing_ksm;
> +}
> +EXPORT_SYMBOL(bio_crypt_should_process);
> +
> +#endif /* CONFIG_BLK_CRYPT_CTX */

Please move these new functions into a separate source file instead of
using #ifdef / #endif. I think the coding style documentation mentions
this explicitly.

> +static struct blk_crypto_keyslot {
> +     struct crypto_skcipher *tfm;
> +     int crypto_alg_id;
> +     union {
> +             u8 key[BLK_CRYPTO_MAX_KEY_SIZE];
> +             u32 key_words[BLK_CRYPTO_MAX_KEY_SIZE/4];
> +     };
> +} *slot_mem;

What is the purpose of the key_words[] member? Is it used anywhere? If
not, can it be left out?

> diff --git a/block/blk-merge.c b/block/blk-merge.c
> index 1c9d4f0f96ea..55133c547bdf 100644
> --- a/block/blk-merge.c
> +++ b/block/blk-merge.c
> @@ -614,6 +614,59 @@ int blk_rq_map_sg(struct request_queue *q, struct 
> request *rq,
>  }
>  EXPORT_SYMBOL(blk_rq_map_sg);
>  
> +#ifdef CONFIG_BLK_CRYPT_CTX
> +/*
> + * Checks that two bio crypt contexts are compatible - i.e. that
> + * they are mergeable except for data_unit_num continuity.
> + */
> +static inline bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2)
> +{
> +     struct bio_crypt_ctx *bc1 = &b_1->bi_crypt_context;
> +     struct bio_crypt_ctx *bc2 = &b_2->bi_crypt_context;
> +
> +     if (bio_is_encrypted(b_1) != bio_is_encrypted(b_2) ||
> +         bc1->keyslot != bc2->keyslot)
> +             return false;
> +
> +     return !bio_is_encrypted(b_1) ||
> +             bc1->data_unit_size_bits == bc2->data_unit_size_bits;
> +}
> +
> +/*
> + * Checks that two bio crypt contexts are compatible, and also
> + * that their data_unit_nums are continuous (and can hence be merged)
> + */
> +static inline bool bio_crypt_ctx_back_mergeable(struct bio *b_1,
> +                                             unsigned int b1_sectors,
> +                                             struct bio *b_2)
> +{
> +     struct bio_crypt_ctx *bc1 = &b_1->bi_crypt_context;
> +     struct bio_crypt_ctx *bc2 = &b_2->bi_crypt_context;
> +
> +     if (!bio_crypt_ctx_compatible(b_1, b_2))
> +             return false;
> +
> +     return !bio_is_encrypted(b_1) ||
> +             (bc1->data_unit_num +
> +             (b1_sectors >> (bc1->data_unit_size_bits - 9)) ==
> +             bc2->data_unit_num);
> +}
> +
> +#else /* CONFIG_BLK_CRYPT_CTX */
> +static inline bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2)
> +{
> +     return true;
> +}
> +
> +static inline bool bio_crypt_ctx_back_mergeable(struct bio *b_1,
> +                                             unsigned int b1_sectors,
> +                                             struct bio *b_2)
> +{
> +     return true;
> +}
> +
> +#endif /* CONFIG_BLK_CRYPT_CTX */

Can the above functions be moved into a new file such that the
#ifdef/#endif construct can be avoided?

> +     /* Wait till there is a free slot available */
> +     while (atomic_read(&ksm->num_idle_slots) == 0) {
> +             mutex_unlock(&ksm->lock);
> +             wait_event(ksm->wait_queue,
> +                        (atomic_read(&ksm->num_idle_slots) > 0));
> +             mutex_lock(&ksm->lock);
> +     }

Using an atomic_read() inside code protected by a mutex is suspicious.
Would protecting all ksm->num_idle_slots manipulations with ksm->lock
and making ksm->num_idle_slots a regular integer have a negative
performance impact?

> +struct keyslot_mgmt_ll_ops {
> +     int (*keyslot_program)(void *ll_priv_data, const u8 *key,
> +                            unsigned int data_unit_size,
> +                            /* crypto_alg_id returned by crypto_alg_find */
> +                            unsigned int crypto_alg_id,
> +                            unsigned int slot);
> +     /**
> +      * Evict key from all keyslots in the keyslot manager.
> +      * The key, data_unit_size and crypto_alg_id are also passed down
> +      * so that for e.g. dm layers that have their own keyslot
> +      * managers can evict keys from the devices that they map over.
> +      * Returns 0 on success, -errno otherwise.
> +      */
> +     int (*keyslot_evict)(void *ll_priv_data, unsigned int slot,
> +                          const u8 *key, unsigned int data_unit_size,
> +                          unsigned int crypto_alg_id);
> +     /**
> +      * Get a crypto_alg_id (used internally by the lower layer driver) that
> +      * represents the given blk-crypto crypt_mode and data_unit_size. The
> +      * returned crypto_alg_id will be used in future calls to the lower
> +      * layer driver (in keyslot_program and keyslot_evict) to reference
> +      * this crypt_mode, data_unit_size combo. Returns negative error code
> +      * if a crypt_mode, data_unit_size combo is not supported.
> +      */
> +     int (*crypto_alg_find)(void *ll_priv_data,
> +                            enum blk_crypt_mode_index crypt_mode,
> +                            unsigned int data_unit_size);
> +     /**
> +      * Returns the slot number that matches the key,
> +      * or -ENOKEY if no match found, or negative on error
> +      */
> +     int (*keyslot_find)(void *ll_priv_data, const u8 *key,
> +                         unsigned int data_unit_size,
> +                         unsigned int crypto_alg_id);
> +};

Have you considered to use kernel-doc format for documenting the members
of the keyslot_mgmt_ll_ops structure?

Thanks,

Bart.

Reply via email to