dm: update target status functions to support IMA measurement
authorTushar Sugandhi <tusharsu@linux.microsoft.com>
Tue, 13 Jul 2021 00:49:03 +0000 (17:49 -0700)
committerMike Snitzer <snitzer@redhat.com>
Tue, 10 Aug 2021 17:34:23 +0000 (13:34 -0400)
For device mapper targets to take advantage of IMA's measurement
capabilities, the status functions for the individual targets need to be
updated to handle the status_type_t case for value STATUSTYPE_IMA.

Update status functions for the following target types, to log their
respective attributes to be measured using IMA.
 01. cache
 02. crypt
 03. integrity
 04. linear
 05. mirror
 06. multipath
 07. raid
 08. snapshot
 09. striped
 10. verity

For rest of the targets, handle the STATUSTYPE_IMA case by setting the
measurement buffer to NULL.

For IMA to measure the data on a given system, the IMA policy on the
system needs to be updated to have the following line, and the system
needs to be restarted for the measurements to take effect.

/etc/ima/ima-policy
 measure func=CRITICAL_DATA label=device-mapper template=ima-buf

The measurements will be reflected in the IMA logs, which are located at:

/sys/kernel/security/integrity/ima/ascii_runtime_measurements
/sys/kernel/security/integrity/ima/binary_runtime_measurements

These IMA logs can later be consumed by various attestation clients
running on the system, and send them to external services for attesting
the system.

The DM target data measured by IMA subsystem can alternatively
be queried from userspace by setting DM_IMA_MEASUREMENT_FLAG with
DM_TABLE_STATUS_CMD.

Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
32 files changed:
drivers/md/dm-cache-target.c
drivers/md/dm-clone-target.c
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-dust.c
drivers/md/dm-ebs-target.c
drivers/md/dm-era-target.c
drivers/md/dm-flakey.c
drivers/md/dm-integrity.c
drivers/md/dm-linear.c
drivers/md/dm-log-userspace-base.c
drivers/md/dm-log-writes.c
drivers/md/dm-log.c
drivers/md/dm-mpath.c
drivers/md/dm-ps-historical-service-time.c
drivers/md/dm-ps-io-affinity.c
drivers/md/dm-ps-queue-length.c
drivers/md/dm-ps-round-robin.c
drivers/md/dm-ps-service-time.c
drivers/md/dm-raid.c
drivers/md/dm-raid1.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-snap-transient.c
drivers/md/dm-snap.c
drivers/md/dm-stripe.c
drivers/md/dm-switch.c
drivers/md/dm-thin.c
drivers/md/dm-unstripe.c
drivers/md/dm-verity-target.c
drivers/md/dm-writecache.c
drivers/md/dm-zoned-target.c
include/linux/device-mapper.h

index 8e4ced5a251607f6affa74bf7a4bc25ba4829e7a..bdd500447dea2e6382d95f9d42bda0494199ce37 100644 (file)
@@ -3122,6 +3122,30 @@ static void cache_status(struct dm_target *ti, status_type_t type,
                        DMEMIT(" %s", cache->ctr_args[i]);
                if (cache->nr_ctr_args)
                        DMEMIT(" %s", cache->ctr_args[cache->nr_ctr_args - 1]);
+               break;
+
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               if (get_cache_mode(cache) == CM_FAIL)
+                       DMEMIT(",metadata_mode=fail");
+               else if (get_cache_mode(cache) == CM_READ_ONLY)
+                       DMEMIT(",metadata_mode=ro");
+               else
+                       DMEMIT(",metadata_mode=rw");
+
+               format_dev_t(buf, cache->metadata_dev->bdev->bd_dev);
+               DMEMIT(",cache_metadata_device=%s", buf);
+               format_dev_t(buf, cache->cache_dev->bdev->bd_dev);
+               DMEMIT(",cache_device=%s", buf);
+               format_dev_t(buf, cache->origin_dev->bdev->bd_dev);
+               DMEMIT(",cache_origin_device=%s", buf);
+               DMEMIT(",writethrough=%c", writethrough_mode(cache) ? 'y' : 'n');
+               DMEMIT(",writeback=%c", writeback_mode(cache) ? 'y' : 'n');
+               DMEMIT(",passthrough=%c", passthrough_mode(cache) ? 'y' : 'n');
+               DMEMIT(",metadata2=%c", cache->features.metadata_version == 2 ? 'y' : 'n');
+               DMEMIT(",no_discard_passdown=%c", cache->features.discard_passdown ? 'n' : 'y');
+               DMEMIT(";");
+               break;
        }
 
        return;
index a90bdf9b2ca6bdbdb8a7b6b7ffa07e9e53d850a2..84dbe08ad20536b264566ba8ddb133beb441897c 100644 (file)
@@ -1499,6 +1499,11 @@ static void clone_status(struct dm_target *ti, status_type_t type,
 
                for (i = 0; i < clone->nr_ctr_args; i++)
                        DMEMIT(" %s", clone->ctr_args[i]);
+               break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 
        return;
index 50f4cbd600d5808f51d2aa17a73f47bbf3890eaf..80fdc42ce3c85ac1b3a718f53a6dfa94c595a55e 100644 (file)
@@ -3485,7 +3485,34 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
                        if (test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags))
                                DMEMIT(" iv_large_sectors");
                }
+               break;
+
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               DMEMIT(",allow_discards=%c", ti->num_discard_bios ? 'y' : 'n');
+               DMEMIT(",same_cpu_crypt=%c", test_bit(DM_CRYPT_SAME_CPU, &cc->flags) ? 'y' : 'n');
+               DMEMIT(",submit_from_crypt_cpus=%c", test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags) ?
+                      'y' : 'n');
+               DMEMIT(",no_read_workqueue=%c", test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags) ?
+                      'y' : 'n');
+               DMEMIT(",no_write_workqueue=%c", test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags) ?
+                      'y' : 'n');
+               DMEMIT(",iv_large_sectors=%c", test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags) ?
+                      'y' : 'n');
 
+               if (cc->on_disk_tag_size)
+                       DMEMIT(",integrity_tag_size=%u,cipher_auth=%s",
+                              cc->on_disk_tag_size, cc->cipher_auth);
+               if (cc->sector_size != (1 << SECTOR_SHIFT))
+                       DMEMIT(",sector_size=%d", cc->sector_size);
+               if (cc->cipher_string)
+                       DMEMIT(",cipher_string=%s", cc->cipher_string);
+
+               DMEMIT(",key_size=%u", cc->key_size);
+               DMEMIT(",key_parts=%u", cc->key_parts);
+               DMEMIT(",key_extra_size=%u", cc->key_extra_size);
+               DMEMIT(",key_mac_size=%u", cc->key_mac_size);
+               DMEMIT(";");
                break;
        }
 }
index 2628a832787b0479c557365a876cabad8c7f8909..59e51d285b0e5903e612ae617f65db687b58efea 100644 (file)
@@ -326,6 +326,10 @@ static void delay_status(struct dm_target *ti, status_type_t type,
                        DMEMIT_DELAY_CLASS(&dc->flush);
                }
                break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 }
 
index cbe1058ee589a1bc5a7a2bbd1e9b4369c2a3273d..3163e2b1418e73b66b28c7df4a68dfa861efe5a5 100644 (file)
@@ -527,6 +527,10 @@ static void dust_status(struct dm_target *ti, status_type_t type,
                DMEMIT("%s %llu %u", dd->dev->name,
                       (unsigned long long)dd->start, dd->blksz);
                break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 }
 
index 71475a2410bea7e57391f9a6f07d17900eb20441..ec8426611cc66fd2aace9b76314fd594dc97cead 100644 (file)
@@ -401,6 +401,9 @@ static void ebs_status(struct dm_target *ti, status_type_t type,
                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;
        }
 }
 
index 3b748393fca5d421539dd3e71d62a6d9b45bbffb..2a78f687414317588da2d5f484e3557d0d82cc79 100644 (file)
@@ -1644,6 +1644,10 @@ static void era_status(struct dm_target *ti, status_type_t type,
                format_dev_t(buf, era->origin_dev->bdev->bd_dev);
                DMEMIT("%s %u", buf, era->sectors_per_block);
                break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 
        return;
index 5877220c01edb63c4c7220d9d3b8a5f6ee09ff97..4b94ffe6f2d4ffc3cd6ad105b7eac52061f2b797 100644 (file)
@@ -440,6 +440,10 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
                               fc->corrupt_bio_value, fc->corrupt_bio_flags);
 
                break;
+
+       case STATUSTYPE_IMA:
+               result[0] = '\0';
+               break;
        }
 }
 
index 20f2510db1f673ba9104222b85163df57ca7c7ad..40f8116c8e443ffcb0cde0c5e50e23c7308f1744 100644 (file)
@@ -3306,6 +3306,31 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
                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(",mode=%c", ic->mode);
+               DMEMIT(";");
+               break;
        }
 }
 
index c91f1e2e2f6564f77f41b0cc69eeaa084c0426ad..679b4c0a2eea1ed50fc79cce36088f51f9e43b13 100644 (file)
@@ -106,6 +106,7 @@ static void linear_status(struct dm_target *ti, status_type_t type,
                          unsigned status_flags, char *result, unsigned maxlen)
 {
        struct linear_c *lc = (struct linear_c *) ti->private;
+       size_t sz = 0;
 
        switch (type) {
        case STATUSTYPE_INFO:
@@ -113,8 +114,13 @@ static void linear_status(struct dm_target *ti, status_type_t type,
                break;
 
        case STATUSTYPE_TABLE:
-               snprintf(result, maxlen, "%s %llu", lc->dev->name,
-                               (unsigned long long)lc->start);
+               DMEMIT("%s %llu", lc->dev->name, (unsigned long long)lc->start);
+               break;
+
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               DMEMIT(",device_name=%s,start=%llu;", lc->dev->name,
+                      (unsigned long long)lc->start);
                break;
        }
 }
index 52090bee17c2836837287630e6046d4e1ec07b4d..9ab93ebea8895d29ff7ef1b9ea601bbd5df68f5f 100644 (file)
@@ -820,6 +820,9 @@ static int userspace_status(struct dm_dirty_log *log, status_type_t status_type,
                        DMEMIT("integrated_flush ");
                DMEMIT("%s ", table_args);
                break;
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
        return (r) ? 0 : (int)sz;
 }
index 57882654ffee79eee87de2b582ccaf124a559000..d93a4db23512414dd09a5e72f424b53b481d38e8 100644 (file)
@@ -834,6 +834,10 @@ static void log_writes_status(struct dm_target *ti, status_type_t type,
        case STATUSTYPE_TABLE:
                DMEMIT("%s %s", lc->dev->name, lc->logdev->name);
                break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 }
 
index 33e71ea6cc1435bf13b7dc88546e30c83ca89083..1ecf75ef276a4c33225a89a69b820e76e6a197d4 100644 (file)
@@ -793,6 +793,11 @@ static int core_status(struct dm_dirty_log *log, status_type_t status,
                DMEMIT("%s %u %u ", log->type->name,
                       lc->sync == DEFAULTSYNC ? 1 : 2, lc->region_size);
                DMEMIT_SYNC;
+               break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 
        return sz;
@@ -817,6 +822,11 @@ static int disk_status(struct dm_dirty_log *log, status_type_t status,
                       lc->sync == DEFAULTSYNC ? 2 : 3, lc->log_dev->name,
                       lc->region_size);
                DMEMIT_SYNC;
+               break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 
        return sz;
index bced42f082b02fadd97467d61222db09bed4cbd1..c3c514a9edbb9a52ee7c35487d705cb7eb9ae630 100644 (file)
@@ -1904,6 +1904,34 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
                        }
                }
                break;
+
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               list_for_each_entry(pg, &m->priority_groups, list) {
+                       if (pg->bypassed)
+                               state = 'D';    /* Disabled */
+                       else if (pg == m->current_pg)
+                               state = 'A';    /* Currently Active */
+                       else
+                               state = 'E';    /* Enabled */
+                       DMEMIT(",pg_state=%c", state);
+                       DMEMIT(",nr_pgpaths=%u", pg->nr_pgpaths);
+                       DMEMIT(",path_selector_name=%s", pg->ps.type->name);
+
+                       list_for_each_entry(p, &pg->pgpaths, list) {
+                               DMEMIT(",path_name=%s,is_active=%c,fail_count=%u",
+                                      p->path.dev->name, p->is_active ? 'A' : 'F',
+                                      p->fail_count);
+                               if (pg->ps.type->status) {
+                                       DMEMIT(",path_selector_status=");
+                                       sz += pg->ps.type->status(&pg->ps, &p->path,
+                                                                 type, result + sz,
+                                                                 maxlen - sz);
+                               }
+                       }
+               }
+               DMEMIT(";");
+               break;
        }
 
        spin_unlock_irqrestore(&m->lock, flags);
index 186f91e2752c1862be6d23b038329b845581b611..1856a1b125cc1bc49749fe878d317f4210c44ce9 100644 (file)
@@ -255,6 +255,9 @@ static int hst_status(struct path_selector *ps, struct dm_path *path,
                case STATUSTYPE_TABLE:
                        DMEMIT("0 ");
                        break;
+               case STATUSTYPE_IMA:
+                       *result = '\0';
+                       break;
                }
        }
 
index cb8e83bfb1a7d74b5b2943d9134d77740deec858..f74501e65a8edd021575ff1b647860eb9d69e46d 100644 (file)
@@ -170,6 +170,9 @@ static int ioa_status(struct path_selector *ps, struct dm_path *path,
                pi = path->pscontext;
                DMEMIT("%*pb ", cpumask_pr_args(pi->cpumask));
                break;
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 
        return sz;
index 5fd018d184187ae0e0c07d7fa75e7f134b5bc8fb..cef70657bbbc2a9c5f47f77b9323f0b8ba0424e3 100644 (file)
@@ -102,6 +102,9 @@ static int ql_status(struct path_selector *ps, struct dm_path *path,
                case STATUSTYPE_TABLE:
                        DMEMIT("%u ", pi->repeat_count);
                        break;
+               case STATUSTYPE_IMA:
+                       *result = '\0';
+                       break;
                }
        }
 
index bdbb7e6e8212bfc050cadbfa42cb1fbabe03bc54..27f44c5fa04e8e91eb82dd502acc8ede7dea45be 100644 (file)
@@ -100,6 +100,10 @@ static int rr_status(struct path_selector *ps, struct dm_path *path,
                        pi = path->pscontext;
                        DMEMIT("%u ", pi->repeat_count);
                        break;
+
+               case STATUSTYPE_IMA:
+                       *result = '\0';
+                       break;
                }
        }
 
index 9cfda665e9ebd3db0431f55b5cdf221749eda0da..3ec9c33265c5211aec6a565d51efed46d45ba9a9 100644 (file)
@@ -99,6 +99,9 @@ static int st_status(struct path_selector *ps, struct dm_path *path,
                        DMEMIT("%u %u ", pi->repeat_count,
                               pi->relative_throughput);
                        break;
+               case STATUSTYPE_IMA:
+                       result[0] = '\0';
+                       break;
                }
        }
 
index bf4a467fc73a416e9dec80b7fb190fbe602a4447..d9ef52159a22bf6f0288b36acdcc1b0a9f2f5f36 100644 (file)
@@ -3671,6 +3671,45 @@ static void raid_status(struct dm_target *ti, status_type_t type,
                for (i = 0; i < rs->raid_disks; i++)
                        DMEMIT(" %s %s", __get_dev_name(rs->dev[i].meta_dev),
                                         __get_dev_name(rs->dev[i].data_dev));
+               break;
+
+       case STATUSTYPE_IMA:
+               rt = get_raid_type_by_ll(mddev->new_level, mddev->new_layout);
+               if (!rt)
+                       return;
+
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               DMEMIT(",raid_type=%s,raid_disks=%d", rt->name, mddev->raid_disks);
+
+               /* Access most recent mddev properties for status output */
+               smp_rmb();
+               recovery = rs->md.recovery;
+               state = decipher_sync_action(mddev, recovery);
+               DMEMIT(",raid_state=%s", sync_str(state));
+
+               for (i = 0; i < rs->raid_disks; i++) {
+                       DMEMIT(",raid_device_%d_status=", i);
+                       DMEMIT(__raid_dev_status(rs, &rs->dev[i].rdev));
+               }
+
+               if (rt_is_raid456(rt)) {
+                       DMEMIT(",journal_dev_mode=");
+                       switch (rs->journal_dev.mode) {
+                       case R5C_JOURNAL_MODE_WRITE_THROUGH:
+                               DMEMIT("%s",
+                                      _raid456_journal_mode[R5C_JOURNAL_MODE_WRITE_THROUGH].param);
+                               break;
+                       case R5C_JOURNAL_MODE_WRITE_BACK:
+                               DMEMIT("%s",
+                                      _raid456_journal_mode[R5C_JOURNAL_MODE_WRITE_BACK].param);
+                               break;
+                       default:
+                               DMEMIT("invalid");
+                               break;
+                       }
+               }
+               DMEMIT(";");
+               break;
        }
 }
 
index ebb4810cc3b40e01e0a8529e5625a03def556bba..8811d484fdd14c77cd97fb567104b3fa9d83f496 100644 (file)
@@ -1435,6 +1435,23 @@ static void mirror_status(struct dm_target *ti, status_type_t type,
                }
 
                break;
+
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               DMEMIT(",nr_mirrors=%d", ms->nr_mirrors);
+               for (m = 0; m < ms->nr_mirrors; m++) {
+                       DMEMIT(",mirror_device_%d=%s", m, ms->mirror[m].dev->name);
+                       DMEMIT(",mirror_device_%d_status=%c",
+                              m, device_status_char(&(ms->mirror[m])));
+               }
+
+               DMEMIT(",handle_errors=%c", errors_handled(ms) ? 'y' : 'n');
+               DMEMIT(",keep_log=%c", keep_log(ms) ? 'y' : 'n');
+
+               DMEMIT(",log_type_status=");
+               sz += log->type->status(log, type, result+sz, maxlen-sz);
+               DMEMIT(";");
+               break;
        }
 }
 
index 9ab4bf651ca9333a7ba995d15d9d0b5370f83db5..3bb5cff5d6fc38acdeab6f27301119816a4cdc50 100644 (file)
@@ -908,6 +908,10 @@ static unsigned persistent_status(struct dm_exception_store *store,
        case STATUSTYPE_TABLE:
                DMEMIT(" %s %llu", store->userspace_supports_overflow ? "PO" : "P",
                       (unsigned long long)store->chunk_size);
+               break;
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 
        return sz;
index 4d50a12cf00c699b85a0df1c0b1dd86f0137b691..0e0ae4c36b37485ddf8a706914026281703aa6c2 100644 (file)
@@ -95,6 +95,10 @@ static unsigned transient_status(struct dm_exception_store *store,
                break;
        case STATUSTYPE_TABLE:
                DMEMIT(" N %llu", (unsigned long long)store->chunk_size);
+               break;
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 
        return sz;
index 751ec5ea1dbb5fcfaf23a28ad171a13b0f44ee92..dcf34c6b05ad35763b09bdaa11857f959c50e320 100644 (file)
@@ -2390,6 +2390,16 @@ static void snapshot_status(struct dm_target *ti, status_type_t type,
                                DMEMIT(" discard_passdown_origin");
                }
                break;
+
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               DMEMIT(",snap_origin_name=%s", snap->origin->name);
+               DMEMIT(",snap_cow_name=%s", snap->cow->name);
+               DMEMIT(",snap_valid=%c", snap->valid ? 'y' : 'n');
+               DMEMIT(",snap_merge_failed=%c", snap->merge_failed ? 'y' : 'n');
+               DMEMIT(",snapshot_overflowed=%c", snap->snapshot_overflowed ? 'y' : 'n');
+               DMEMIT(";");
+               break;
        }
 }
 
@@ -2734,6 +2744,9 @@ static void origin_status(struct dm_target *ti, status_type_t type,
        case STATUSTYPE_TABLE:
                snprintf(result, maxlen, "%s", o->dev->name);
                break;
+       case STATUSTYPE_IMA:
+               result[0] = '\0';
+               break;
        }
 }
 
index df359d33cda89195edc444f66b4e163844ab45c5..6660b6b53d5bf4aa5c833549f96d6e18485598af 100644 (file)
@@ -428,6 +428,21 @@ static void stripe_status(struct dm_target *ti, status_type_t type,
                        DMEMIT(" %s %llu", sc->stripe[i].dev->name,
                            (unsigned long long)sc->stripe[i].physical_start);
                break;
+
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               DMEMIT(",stripes=%d,chunk_size=%llu", sc->stripes,
+                      (unsigned long long)sc->chunk_size);
+
+               for (i = 0; i < sc->stripes; i++) {
+                       DMEMIT(",stripe_%d_device_name=%s", i, sc->stripe[i].dev->name);
+                       DMEMIT(",stripe_%d_physical_start=%llu", i,
+                              (unsigned long long)sc->stripe[i].physical_start);
+                       DMEMIT(",stripe_%d_status=%c", i,
+                              atomic_read(&(sc->stripe[i].error_count)) ? 'D' : 'A');
+               }
+               DMEMIT(";");
+               break;
        }
 }
 
index 262e2b0fd97502c1358c653da1b6ed8974a1f76e..028a92ff6d5767097fe38f043194a9f37c592f54 100644 (file)
@@ -504,6 +504,10 @@ static void switch_status(struct dm_target *ti, status_type_t type,
                        DMEMIT(" %s %llu", sctx->path_list[path_nr].dmdev->name,
                               (unsigned long long)sctx->path_list[path_nr].start);
                break;
+
+       case STATUSTYPE_IMA:
+               result[0] = '\0';
+               break;
        }
 }
 
index 985baee3a678e8fa57a7d3a21212d67c7514d182..4c67b77c23c1b98fe550f05c3b4b8fbe4c3daac4 100644 (file)
@@ -4012,6 +4012,10 @@ static void pool_status(struct dm_target *ti, status_type_t type,
                       (unsigned long long)pt->low_water_blocks);
                emit_flags(&pt->requested_pf, result, sz, maxlen);
                break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
        return;
 
@@ -4423,6 +4427,10 @@ static void thin_status(struct dm_target *ti, status_type_t type,
                        if (tc->origin_dev)
                                DMEMIT(" %s", format_dev_t(buf, tc->origin_dev->bdev->bd_dev));
                        break;
+
+               case STATUSTYPE_IMA:
+                       *result = '\0';
+                       break;
                }
        }
 
index 7357c1bd58631d6ed80e249856cce41a1d5316b3..fdc8921e5c19f01947335a85c956df89f1a0cf23 100644 (file)
@@ -156,6 +156,10 @@ static void unstripe_status(struct dm_target *ti, status_type_t type,
                       uc->stripes, (unsigned long long)uc->chunk_size, uc->unstripe,
                       uc->dev->name, (unsigned long long)uc->physical_start);
                break;
+
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 }
 
index d3e76aefc1a6c0591150a21ba2412c1788e342ec..bfefa100c265c62c5e534d3ef5998f510ce9c572 100644 (file)
@@ -772,6 +772,47 @@ static void verity_status(struct dm_target *ti, status_type_t type,
                        DMEMIT(" " DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY
                                " %s", v->signature_key_desc);
                break;
+
+       case STATUSTYPE_IMA:
+               DMEMIT_TARGET_NAME_VERSION(ti->type);
+               DMEMIT(",hash_failed=%c", v->hash_failed ? 'C' : 'V');
+               DMEMIT(",verity_version=%u", v->version);
+               DMEMIT(",data_device_name=%s", v->data_dev->name);
+               DMEMIT(",hash_device_name=%s", v->hash_dev->name);
+               DMEMIT(",verity_algorithm=%s", v->alg_name);
+
+               DMEMIT(",root_digest=");
+               for (x = 0; x < v->digest_size; x++)
+                       DMEMIT("%02x", v->root_digest[x]);
+
+               DMEMIT(",salt=");
+               if (!v->salt_size)
+                       DMEMIT("-");
+               else
+                       for (x = 0; x < v->salt_size; x++)
+                               DMEMIT("%02x", v->salt[x]);
+
+               DMEMIT(",ignore_zero_blocks=%c", v->zero_digest ? 'y' : 'n');
+               DMEMIT(",check_at_most_once=%c", v->validated_blocks ? 'y' : 'n');
+
+               if (v->mode != DM_VERITY_MODE_EIO) {
+                       DMEMIT(",verity_mode=");
+                       switch (v->mode) {
+                       case DM_VERITY_MODE_LOGGING:
+                               DMEMIT(DM_VERITY_OPT_LOGGING);
+                               break;
+                       case DM_VERITY_MODE_RESTART:
+                               DMEMIT(DM_VERITY_OPT_RESTART);
+                               break;
+                       case DM_VERITY_MODE_PANIC:
+                               DMEMIT(DM_VERITY_OPT_PANIC);
+                               break;
+                       default:
+                               DMEMIT("invalid");
+                       }
+               }
+               DMEMIT(";");
+               break;
        }
 }
 
index e1d7234eec3f5e745d7682baa776043abaa38967..18320444fb0a9b71a2bba75fec062a54a0c03f68 100644 (file)
@@ -2723,6 +2723,9 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
                if (wc->pause_set)
                        DMEMIT(" pause_writeback %u", wc->pause_value);
                break;
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
 }
 
index 7e88df64d197b149a2a92bd1bc42eb35375c51bd..ae1bc48c0043d517d39e5d17fdd1b54953d438fe 100644 (file)
@@ -1119,6 +1119,9 @@ static void dmz_status(struct dm_target *ti, status_type_t type,
                        DMEMIT(" %s", buf);
                }
                break;
+       case STATUSTYPE_IMA:
+               *result = '\0';
+               break;
        }
        return;
 }
index 74486c332946ec867a8b3699d51a22a18d7fcf1f..a92260273eb2c4da5daaf54d574e82cf12667dd4 100644 (file)
@@ -603,6 +603,10 @@ void dm_destroy_keyslot_manager(struct blk_keyslot_manager *ksm);
 #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.
  */