]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Merge tag 'vfs-7.1-rc1.integrity' of git://git.kernel.org/pub/scm/linux/kernel/git... master
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Apr 2026 17:40:26 +0000 (10:40 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 13 Apr 2026 17:40:26 +0000 (10:40 -0700)
Pull vfs integrity updates from Christian Brauner:
 "This adds support to generate and verify integrity information (aka
  T10 PI) in the file system, instead of the automatic below the covers
  support that is currently used.

  The implementation is based on refactoring the existing block layer PI
  code to be reusable for this use case, and then adding relatively
  small wrappers for the file system use case. These are then used in
  iomap to implement the semantics, and wired up in XFS with a small
  amount of glue code.

  Compared to the baseline this does not change performance for writes,
  but increases read performance up to 15% for 4k I/O, with the benefit
  decreasing with larger I/O sizes as even the baseline maxes out the
  device quickly on my older enterprise SSD"

* tag 'vfs-7.1-rc1.integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  xfs: support T10 protection information
  iomap: support T10 protection information
  iomap: support ioends for buffered reads
  iomap: add a bioset pointer to iomap_read_folio_ops
  ntfs3: remove copy and pasted iomap code
  iomap: allow file systems to hook into buffered read bio submission
  iomap: only call into ->submit_read when there is a read_ctx
  iomap: pass the iomap_iter to ->submit_read
  iomap: refactor iomap_bio_read_folio_range
  block: pass a maxlen argument to bio_iov_iter_bounce
  block: add fs_bio_integrity helpers
  block: make max_integrity_io_size public
  block: prepare generation / verification helpers for fs usage
  block: add a bdev_has_integrity_csum helper
  block: factor out a bio_integrity_setup_default helper
  block: factor out a bio_integrity_action helper

1  2 
fs/fuse/file.c
fs/iomap/bio.c
fs/iomap/buffered-io.c

diff --cc fs/fuse/file.c
Simple merge
diff --cc fs/iomap/bio.c
index edd908183058f5de697be7e9df47096262c424a1,f989ffcaac96d9c482210f0b76bfba69d6abad90..4504f4633f17592cbc24a5f102f7b5c00959971a
@@@ -8,66 -9,33 +9,77 @@@
  #include "internal.h"
  #include "trace.h"
  
- static void __iomap_read_end_io(struct bio *bio)
 +static DEFINE_SPINLOCK(failed_read_lock);
 +static struct bio_list failed_read_list = BIO_EMPTY_LIST;
 +
+ static u32 __iomap_read_end_io(struct bio *bio, int error)
  {
-       int error = blk_status_to_errno(bio->bi_status);
        struct folio_iter fi;
+       u32 folio_count = 0;
  
-       bio_for_each_folio_all(fi, bio)
+       bio_for_each_folio_all(fi, bio) {
                iomap_finish_folio_read(fi.folio, fi.offset, fi.length, error);
+               folio_count++;
+       }
+       if (bio_integrity(bio))
+               fs_bio_integrity_free(bio);
        bio_put(bio);
+       return folio_count;
  }
  
-               __iomap_read_end_io(bio);
 +static void
 +iomap_fail_reads(
 +      struct work_struct      *work)
 +{
 +      struct bio              *bio;
 +      struct bio_list         tmp = BIO_EMPTY_LIST;
 +      unsigned long           flags;
 +
 +      spin_lock_irqsave(&failed_read_lock, flags);
 +      bio_list_merge_init(&tmp, &failed_read_list);
 +      spin_unlock_irqrestore(&failed_read_lock, flags);
 +
 +      while ((bio = bio_list_pop(&tmp)) != NULL) {
++              __iomap_read_end_io(bio, blk_status_to_errno(bio->bi_status));
 +              cond_resched();
 +      }
 +}
 +
 +static DECLARE_WORK(failed_read_work, iomap_fail_reads);
 +
 +static void iomap_fail_buffered_read(struct bio *bio)
 +{
 +      unsigned long flags;
 +
 +      /*
 +       * Bounce I/O errors to a workqueue to avoid nested i_lock acquisitions
 +       * in the fserror code.  The caller no longer owns the bio reference
 +       * after the spinlock drops.
 +       */
 +      spin_lock_irqsave(&failed_read_lock, flags);
 +      if (bio_list_empty(&failed_read_list))
 +              WARN_ON_ONCE(!schedule_work(&failed_read_work));
 +      bio_list_add(&failed_read_list, bio);
 +      spin_unlock_irqrestore(&failed_read_lock, flags);
 +}
 +
  static void iomap_read_end_io(struct bio *bio)
  {
 -      __iomap_read_end_io(bio, blk_status_to_errno(bio->bi_status));
 +      if (bio->bi_status) {
 +              iomap_fail_buffered_read(bio);
 +              return;
 +      }
 +
-       __iomap_read_end_io(bio);
++      __iomap_read_end_io(bio, 0);
+ }
+ u32 iomap_finish_ioend_buffered_read(struct iomap_ioend *ioend)
+ {
+       return __iomap_read_end_io(&ioend->io_bio, ioend->io_error);
  }
  
- static void iomap_bio_submit_read(struct iomap_read_folio_ctx *ctx)
+ static void iomap_bio_submit_read(const struct iomap_iter *iter,
+               struct iomap_read_folio_ctx *ctx)
  {
        struct bio *bio = ctx->read_ctx;
  
Simple merge