Merge tag 'for-5.15/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Aug 2021 21:55:09 +0000 (14:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Aug 2021 21:55:09 +0000 (14:55 -0700)
Pull device mapper updates from Mike Snitzer:

 - Add DM infrastructure for IMA-based remote attestion. These changes
   are the basis for deploying DM-based storage in a "cloud" that must
   validate configurations end-users run to maintain trust. These DM
   changes allow supported DM targets' configurations to be measured via
   IMA. But the policy and enforcement (of which configurations are
   valid) is managed by something outside the kernel (e.g. Keylime).

 - Fix DM crypt scalability regression on systems with many cpus due to
   percpu_counter spinlock contention in crypt_page_alloc().

 - Use in_hardirq() instead of deprecated in_irq() in DM crypt.

 - Add event counters to DM writecache to allow users to further assess
   how the writecache is performing.

 - Various code cleanup in DM writecache's main IO mapping function.

* tag 'for-5.15/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm crypt: use in_hardirq() instead of deprecated in_irq()
  dm ima: update dm documentation for ima measurement support
  dm ima: update dm target attributes for ima measurements
  dm ima: add a warning in dm_init if duplicate ima events are not measured
  dm ima: prefix ima event name related to device mapper with dm_
  dm ima: add version info to dm related events in ima log
  dm ima: prefix dm table hashes in ima log with hash algorithm
  dm crypt: Avoid percpu_counter spinlock contention in crypt_page_alloc()
  dm: add documentation for IMA measurement support
  dm: update target status functions to support IMA measurement
  dm ima: measure data on device rename
  dm ima: measure data on table clear
  dm ima: measure data on device remove
  dm ima: measure data on device resume
  dm ima: measure data on table load
  dm writecache: add event counters
  dm writecache: report invalid return from writecache_map helpers
  dm writecache: further writecache_map() cleanup
  dm writecache: factor out writecache_map_remap_origin()
  dm writecache: split up writecache_map() to improve code readability

1  2 
drivers/md/dm-ebs-target.c
drivers/md/dm-integrity.c
include/linux/device-mapper.h

@@@ -74,7 -74,7 +74,7 @@@ static int __ebs_rw_bvec(struct ebs_c *
        if (unlikely(!bv->bv_page || !bv_len))
                return -EIO;
  
 -      pa = page_address(bv->bv_page) + bv->bv_offset;
 +      pa = bvec_virt(bv);
  
        /* Handle overlapping page <-> blocks */
        while (bv_len) {
@@@ -401,6 -401,9 +401,9 @@@ static void ebs_status(struct dm_targe
                snprintf(result, maxlen, ec->u_bs_set ? "%s %llu %u %u" : "%s %llu %u",
                         ec->dev->name, (unsigned long long) ec->start, ec->e_bs, ec->u_bs);
                break;
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
  }
  
@@@ -1819,7 -1819,7 +1819,7 @@@ again
                                unsigned this_len;
  
                                BUG_ON(PageHighMem(biv.bv_page));
 -                              tag = lowmem_page_address(biv.bv_page) + biv.bv_offset;
 +                              tag = bvec_virt(&biv);
                                this_len = min(biv.bv_len, data_to_process);
                                r = dm_integrity_rw_tag(ic, tag, &dio->metadata_block, &dio->metadata_offset,
                                                        this_len, dio->op == REQ_OP_READ ? TAG_READ : TAG_WRITE);
@@@ -2006,7 -2006,7 +2006,7 @@@ retry_kmap
                                        unsigned tag_now = min(biv.bv_len, tag_todo);
                                        char *tag_addr;
                                        BUG_ON(PageHighMem(biv.bv_page));
 -                                      tag_addr = lowmem_page_address(biv.bv_page) + biv.bv_offset;
 +                                      tag_addr = bvec_virt(&biv);
                                        if (likely(dio->op == REQ_OP_WRITE))
                                                memcpy(tag_ptr, tag_addr, tag_now);
                                        else
@@@ -3306,6 -3306,30 +3306,30 @@@ static void dm_integrity_status(struct 
                EMIT_ALG(journal_mac_alg, "journal_mac");
                break;
        }
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               DMEMIT(",dev_name=%s,start=%llu,tag_size=%u,mode=%c",
+                       ic->dev->name, ic->start, ic->tag_size, ic->mode);
+               if (ic->meta_dev)
+                       DMEMIT(",meta_device=%s", ic->meta_dev->name);
+               if (ic->sectors_per_block != 1)
+                       DMEMIT(",block_size=%u", ic->sectors_per_block << SECTOR_SHIFT);
+               DMEMIT(",recalculate=%c", (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) ?
+                      'y' : 'n');
+               DMEMIT(",allow_discards=%c", ic->discard ? 'y' : 'n');
+               DMEMIT(",fix_padding=%c",
+                      ((ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_PADDING)) != 0) ? 'y' : 'n');
+               DMEMIT(",fix_hmac=%c",
+                      ((ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_HMAC)) != 0) ? 'y' : 'n');
+               DMEMIT(",legacy_recalculate=%c", ic->legacy_recalculate ? 'y' : 'n');
+               DMEMIT(",journal_sectors=%u", ic->initial_sectors - SB_SECTORS);
+               DMEMIT(",interleave_sectors=%u", 1U << ic->sb->log2_interleave_sectors);
+               DMEMIT(",buffer_sectors=%u", 1U << ic->log2_buffer_sectors);
+               DMEMIT(";");
+               break;
        }
  }
  
@@@ -31,7 -31,7 +31,7 @@@ enum dm_queue_mode 
        DM_TYPE_DAX_BIO_BASED    = 3,
  };
  
- typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t;
+ typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE, STATUSTYPE_IMA } status_type_t;
  
  union map_info {
        void *ptr;
@@@ -151,6 -151,7 +151,6 @@@ typedef size_t (*dm_dax_copy_iter_fn)(s
                void *addr, size_t bytes, struct iov_iter *i);
  typedef int (*dm_dax_zero_page_range_fn)(struct dm_target *ti, pgoff_t pgoff,
                size_t nr_pages);
 -#define PAGE_SECTORS (PAGE_SIZE / 512)
  
  void dm_error(const char *message);
  
@@@ -602,6 -603,10 +602,10 @@@ void dm_destroy_keyslot_manager(struct 
  #define DMEMIT(x...) sz += ((sz >= maxlen) ? \
                          0 : scnprintf(result + sz, maxlen - sz, x))
  
+ #define DMEMIT_TARGET_NAME_VERSION(y) \
+               DMEMIT("target_name=%s,target_version=%u.%u.%u", \
+                      (y)->name, (y)->version[0], (y)->version[1], (y)->version[2])
  /*
   * Definitions of return values from target end_io function.
   */