1. 03 Jul, 2024 6 commits
    • Eric Biggers's avatar
      dm-verity: hash blocks with shash import+finup when possible · b76ad884
      Eric Biggers authored
      Currently dm-verity computes the hash of each block by using multiple
      calls to the "ahash" crypto API.  While the exact sequence depends on
      the chosen dm-verity settings, in the vast majority of cases it is:
      
          1. crypto_ahash_init()
          2. crypto_ahash_update() [salt]
          3. crypto_ahash_update() [data]
          4. crypto_ahash_final()
      
      This is inefficient for two main reasons:
      
      - It makes multiple indirect calls, which is expensive on modern CPUs
        especially when mitigations for CPU vulnerabilities are enabled.
      
        Since the salt is the same across all blocks on a given dm-verity
        device, a much more efficient sequence would be to do an import of the
        pre-salted state, then a finup.
      
      - It uses the ahash (asynchronous hash) API, despite the fact that
        CPU-based hashing is almost always used in practice, and therefore it
        experiences the overhead of the ahash-based wrapper for shash.
      
        Because dm-verity was intentionally converted to ahash to support
        off-CPU crypto accelerators, a full reversion to shash might not be
        acceptable.  Yet, we should still provide a fast path for shash with
        the most common dm-verity settings.
      
        Another reason for shash over ahash is that the upcoming multibuffer
        hashing support, which is specific to CPU-based hashing, is much
        better suited for shash than for ahash.  Supporting it via ahash would
        add significant complexity and overhead.  And it's not possible for
        the "same" code to properly support both multibuffer hashing and HW
        accelerators at the same time anyway, given the different computation
        models.  Unfortunately there will always be code specific to each
        model needed (for users who want to support both).
      
      Therefore, this patch adds a new shash import+finup based fast path to
      dm-verity.  It is used automatically when appropriate.  This makes
      dm-verity optimized for what the vast majority of users want: CPU-based
      hashing with the most common settings, while still retaining support for
      rarer settings and off-CPU crypto accelerators.
      
      In benchmarks with veritysetup's default parameters (SHA-256, 4K data
      and hash block sizes, 32-byte salt), which also match the parameters
      that Android currently uses, this patch improves block hashing
      performance by about 15% on x86_64 using the SHA-NI instructions, or by
      about 5% on arm64 using the ARMv8 SHA2 instructions.  On x86_64 roughly
      two-thirds of the improvement comes from the use of import and finup,
      while the remaining third comes from the switch from ahash to shash.
      
      Note that another benefit of using "import" to handle the salt is that
      if the salt size is equal to the input size of the hash algorithm's
      compression function, e.g. 64 bytes for SHA-256, then the performance is
      exactly the same as no salt.  This doesn't seem to be much better than
      veritysetup's current default of 32-byte salts, due to the way SHA-256's
      finalization padding works, but it should be marginally better.
      Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
      Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
      Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
      Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
      b76ad884
    • Eric Biggers's avatar
      dm-verity: make verity_hash() take dm_verity_io instead of ahash_request · e8f5e933
      Eric Biggers authored
      In preparation for adding shash support to dm-verity, change
      verity_hash() to take a pointer to a struct dm_verity_io instead of a
      pointer to the ahash_request embedded inside it.
      Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
      Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
      Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
      Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
      e8f5e933
    • Eric Biggers's avatar
      dm-verity: always "map" the data blocks · cf715f4b
      Eric Biggers authored
      dm-verity needs to access data blocks by virtual address in three
      different cases (zeroization, recheck, and forward error correction),
      and one more case (shash support) is coming.  Since it's guaranteed that
      dm-verity data blocks never cross pages, and kmap_local_page and
      kunmap_local are no-ops on modern platforms anyway, just unconditionally
      "map" every data block's page and work with the virtual buffer directly.
      This simplifies the code and eliminates unnecessary overhead.
      Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
      Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
      Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
      Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
      cf715f4b
    • Eric Biggers's avatar
      dm-verity: provide dma_alignment limit in io_hints · 09d14308
      Eric Biggers authored
      Since Linux v6.1, some filesystems support submitting direct I/O that is
      aligned to only dma_alignment instead of the logical_block_size
      alignment that was required before.  I/O that is not aligned to the
      logical_block_size is difficult to handle in device-mapper targets that
      do cryptographic processing of data, as it makes the units of data that
      are hashed or encrypted possibly be split across pages, creating rarely
      used and rarely tested edge cases.
      
      As such, dm-crypt and dm-integrity have already opted out of this by
      setting dma_alignment to 'logical_block_size - 1'.
      
      Although dm-verity does have code that handles these cases (or at least
      is intended to do so), supporting direct I/O with such a low amount of
      alignment is not really useful on dm-verity devices.  So, opt dm-verity
      out of it too so that it's not necessary to handle these edge cases.
      Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
      Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
      Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
      Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
      09d14308
    • Eric Biggers's avatar
      dm-verity: make real_digest and want_digest fixed-length · a7ddb3d4
      Eric Biggers authored
      Change the digest fields in struct dm_verity_io from variable-length to
      fixed-length, since their maximum length is fixed at
      HASH_MAX_DIGESTSIZE, i.e. 64 bytes, which is not too big.  This is
      simpler and makes the fields a bit faster to access.
      
      (HASH_MAX_DIGESTSIZE did not exist when this code was written, which may
      explain why it wasn't used.)
      
      This makes the verity_io_real_digest() and verity_io_want_digest()
      functions trivial, but this patch leaves them in place temporarily since
      most of their callers will go away in a later patch anyway.
      Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
      Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
      Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
      Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
      a7ddb3d4
    • Eric Biggers's avatar
      dm-verity: move data hash mismatch handling into its own function · e41e52e5
      Eric Biggers authored
      Move the code that handles mismatches of data block hashes into its own
      function so that it doesn't clutter up verity_verify_io().
      Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
      Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
      Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
      Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
      e41e52e5
  2. 02 Jul, 2024 6 commits
  3. 26 Jun, 2024 2 commits
    • Mikulas Patocka's avatar
      dm: optimize flushes · aaa53168
      Mikulas Patocka authored
      Device mapper sends flush bios to all the targets and the targets send it
      to the underlying device. That may be inefficient, for example if a table
      contains 10 linear targets pointing to the same physical device, then
      device mapper would send 10 flush bios to that device - despite the fact
      that only one bio would be sufficient.
      
      This commit optimizes the flush behavior. It introduces a per-target
      variable flush_bypasses_map - it is set when the target supports flush
      optimization - currently, the dm-linear and dm-stripe targets support it.
      When all the targets in a table have flush_bypasses_map,
      flush_bypasses_map on the table is set. __send_empty_flush tests if the
      table has flush_bypasses_map - and if it has, no flush bios are sent to
      the targets via the "map" method and the list dm_table->devices is
      iterated and the flush bios are sent to each member of the list.
      Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
      Reviewed-by: default avatarMike Snitzer <snitzer@kernel.org>
      Suggested-by: default avatarYang Yang <yang.yang@vivo.com>
      aaa53168
    • Mikulas Patocka's avatar
      block: change rq_integrity_vec to respect the iterator · cf546dd2
      Mikulas Patocka authored
      If we allocate a bio that is larger than NVMe maximum request size,
      attach integrity metadata to it and send it to the NVMe subsystem, the
      integrity metadata will be corrupted.
      
      Splitting the bio works correctly. The function bio_split will clone the
      bio, trim the iterator of the first bio and advance the iterator of the
      second bio.
      
      However, the function rq_integrity_vec has a bug - it returns the first
      vector of the bio's metadata and completely disregards the metadata
      iterator that was advanced when the bio was split. Thus, the second bio
      uses the same metadata as the first bio and this leads to metadata
      corruption.
      
      This commit changes rq_integrity_vec, so that it calls mp_bvec_iter_bvec
      instead of returning the first vector. mp_bvec_iter_bvec reads the
      iterator and uses it to build a bvec for the current position in the
      iterator.
      
      The "queue_max_integrity_segments(rq->q) > 1" check was removed, because
      the updated rq_integrity_vec function works correctly with multiple
      segments.
      Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
      Reviewed-by: default avatarAnuj Gupta <anuj20.g@samsung.com>
      Reviewed-by: default avatarKanchan Joshi <joshi.k@samsung.com>
      Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
      Link: https://lore.kernel.org/r/49d1afaa-f934-6ed2-a678-e0d428c63a65@redhat.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
      cf546dd2
  4. 24 Jun, 2024 2 commits
  5. 23 Jun, 2024 1 commit
  6. 21 Jun, 2024 4 commits
  7. 20 Jun, 2024 18 commits
  8. 19 Jun, 2024 1 commit
    • Jens Axboe's avatar
      Merge branch 'for-6.11/block-limits' into for-6.11/block · 69c34f07
      Jens Axboe authored
      Merge in last round of queue limits changes from Christoph.
      
      * for-6.11/block-limits: (26 commits)
        block: move the bounce flag into the features field
        block: move the skip_tagset_quiesce flag to queue_limits
        block: move the pci_p2pdma flag to queue_limits
        block: move the zone_resetall flag to queue_limits
        block: move the zoned flag into the features field
        block: move the poll flag to queue_limits
        block: move the dax flag to queue_limits
        block: move the nowait flag to queue_limits
        block: move the synchronous flag to queue_limits
        block: move the stable_writes flag to queue_limits
        block: move the io_stat flag setting to queue_limits
        block: move the add_random flag to queue_limits
        block: move the nonrot flag to queue_limits
        block: move cache control settings out of queue->flags
        block: remove blk_flush_policy
        block: freeze the queue in queue_attr_store
        nbd: move setting the cache control flags to __nbd_set_size
        virtio_blk: remove virtblk_update_cache_mode
        loop: fold loop_update_rotational into loop_reconfigure_limits
        loop: also use the default block size from an underlying block device
        ...
      Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
      69c34f07