|
@@ -225,6 +225,8 @@ struct dm_integrity_c {
|
|
|
struct alg_spec internal_hash_alg;
|
|
|
struct alg_spec journal_crypt_alg;
|
|
|
struct alg_spec journal_mac_alg;
|
|
|
+
|
|
|
+ atomic64_t number_of_mismatches;
|
|
|
};
|
|
|
|
|
|
struct dm_integrity_range {
|
|
@@ -298,7 +300,7 @@ static void __DEBUG_bytes(__u8 *bytes, size_t len, const char *msg, ...)
|
|
|
/*
|
|
|
* DM Integrity profile, protection is performed layer above (dm-crypt)
|
|
|
*/
|
|
|
-static struct blk_integrity_profile dm_integrity_profile = {
|
|
|
+static const struct blk_integrity_profile dm_integrity_profile = {
|
|
|
.name = "DM-DIF-EXT-TAG",
|
|
|
.generate_fn = NULL,
|
|
|
.verify_fn = NULL,
|
|
@@ -310,6 +312,8 @@ static void dm_integrity_dtr(struct dm_target *ti);
|
|
|
|
|
|
static void dm_integrity_io_error(struct dm_integrity_c *ic, const char *msg, int err)
|
|
|
{
|
|
|
+ if (err == -EILSEQ)
|
|
|
+ atomic64_inc(&ic->number_of_mismatches);
|
|
|
if (!cmpxchg(&ic->failed, 0, err))
|
|
|
DMERR("Error on %s: %d", msg, err);
|
|
|
}
|
|
@@ -770,13 +774,13 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi
|
|
|
unsigned i;
|
|
|
|
|
|
io_comp.ic = ic;
|
|
|
- io_comp.comp = COMPLETION_INITIALIZER_ONSTACK(io_comp.comp);
|
|
|
+ init_completion(&io_comp.comp);
|
|
|
|
|
|
if (commit_start + commit_sections <= ic->journal_sections) {
|
|
|
io_comp.in_flight = (atomic_t)ATOMIC_INIT(1);
|
|
|
if (ic->journal_io) {
|
|
|
crypt_comp_1.ic = ic;
|
|
|
- crypt_comp_1.comp = COMPLETION_INITIALIZER_ONSTACK(crypt_comp_1.comp);
|
|
|
+ init_completion(&crypt_comp_1.comp);
|
|
|
crypt_comp_1.in_flight = (atomic_t)ATOMIC_INIT(0);
|
|
|
encrypt_journal(ic, true, commit_start, commit_sections, &crypt_comp_1);
|
|
|
wait_for_completion_io(&crypt_comp_1.comp);
|
|
@@ -792,18 +796,18 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi
|
|
|
to_end = ic->journal_sections - commit_start;
|
|
|
if (ic->journal_io) {
|
|
|
crypt_comp_1.ic = ic;
|
|
|
- crypt_comp_1.comp = COMPLETION_INITIALIZER_ONSTACK(crypt_comp_1.comp);
|
|
|
+ init_completion(&crypt_comp_1.comp);
|
|
|
crypt_comp_1.in_flight = (atomic_t)ATOMIC_INIT(0);
|
|
|
encrypt_journal(ic, true, commit_start, to_end, &crypt_comp_1);
|
|
|
if (try_wait_for_completion(&crypt_comp_1.comp)) {
|
|
|
rw_journal(ic, REQ_OP_WRITE, REQ_FUA, commit_start, to_end, &io_comp);
|
|
|
- crypt_comp_1.comp = COMPLETION_INITIALIZER_ONSTACK(crypt_comp_1.comp);
|
|
|
+ reinit_completion(&crypt_comp_1.comp);
|
|
|
crypt_comp_1.in_flight = (atomic_t)ATOMIC_INIT(0);
|
|
|
encrypt_journal(ic, true, 0, commit_sections - to_end, &crypt_comp_1);
|
|
|
wait_for_completion_io(&crypt_comp_1.comp);
|
|
|
} else {
|
|
|
crypt_comp_2.ic = ic;
|
|
|
- crypt_comp_2.comp = COMPLETION_INITIALIZER_ONSTACK(crypt_comp_2.comp);
|
|
|
+ init_completion(&crypt_comp_2.comp);
|
|
|
crypt_comp_2.in_flight = (atomic_t)ATOMIC_INIT(0);
|
|
|
encrypt_journal(ic, true, 0, commit_sections - to_end, &crypt_comp_2);
|
|
|
wait_for_completion_io(&crypt_comp_1.comp);
|
|
@@ -1041,7 +1045,7 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se
|
|
|
memcpy(tag, dp, to_copy);
|
|
|
} else if (op == TAG_WRITE) {
|
|
|
memcpy(dp, tag, to_copy);
|
|
|
- dm_bufio_mark_buffer_dirty(b);
|
|
|
+ dm_bufio_mark_partial_buffer_dirty(b, *metadata_offset, *metadata_offset + to_copy);
|
|
|
} else {
|
|
|
/* e.g.: op == TAG_CMP */
|
|
|
if (unlikely(memcmp(dp, tag, to_copy))) {
|
|
@@ -1275,6 +1279,7 @@ again:
|
|
|
DMERR("Checksum failed at sector 0x%llx",
|
|
|
(unsigned long long)(sector - ((r + ic->tag_size - 1) / ic->tag_size)));
|
|
|
r = -EILSEQ;
|
|
|
+ atomic64_inc(&ic->number_of_mismatches);
|
|
|
}
|
|
|
if (likely(checksums != checksums_onstack))
|
|
|
kfree(checksums);
|
|
@@ -1676,7 +1681,7 @@ sleep:
|
|
|
dio->in_flight = (atomic_t)ATOMIC_INIT(2);
|
|
|
|
|
|
if (need_sync_io) {
|
|
|
- read_comp = COMPLETION_INITIALIZER_ONSTACK(read_comp);
|
|
|
+ init_completion(&read_comp);
|
|
|
dio->completion = &read_comp;
|
|
|
} else
|
|
|
dio->completion = NULL;
|
|
@@ -1700,7 +1705,11 @@ sleep:
|
|
|
|
|
|
if (need_sync_io) {
|
|
|
wait_for_completion_io(&read_comp);
|
|
|
- integrity_metadata(&dio->work);
|
|
|
+ if (likely(!bio->bi_status))
|
|
|
+ integrity_metadata(&dio->work);
|
|
|
+ else
|
|
|
+ dec_in_flight(dio);
|
|
|
+
|
|
|
} else {
|
|
|
INIT_WORK(&dio->work, integrity_metadata);
|
|
|
queue_work(ic->metadata_wq, &dio->work);
|
|
@@ -1834,7 +1843,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
|
|
|
|
|
|
comp.ic = ic;
|
|
|
comp.in_flight = (atomic_t)ATOMIC_INIT(1);
|
|
|
- comp.comp = COMPLETION_INITIALIZER_ONSTACK(comp.comp);
|
|
|
+ init_completion(&comp.comp);
|
|
|
|
|
|
i = write_start;
|
|
|
for (n = 0; n < write_sections; n++, i++, wraparound_section(ic, &i)) {
|
|
@@ -2061,7 +2070,7 @@ static void replay_journal(struct dm_integrity_c *ic)
|
|
|
if (ic->journal_io) {
|
|
|
struct journal_completion crypt_comp;
|
|
|
crypt_comp.ic = ic;
|
|
|
- crypt_comp.comp = COMPLETION_INITIALIZER_ONSTACK(crypt_comp.comp);
|
|
|
+ init_completion(&crypt_comp.comp);
|
|
|
crypt_comp.in_flight = (atomic_t)ATOMIC_INIT(0);
|
|
|
encrypt_journal(ic, false, 0, ic->journal_sections, &crypt_comp);
|
|
|
wait_for_completion(&crypt_comp.comp);
|
|
@@ -2233,7 +2242,7 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
|
|
|
|
|
|
switch (type) {
|
|
|
case STATUSTYPE_INFO:
|
|
|
- result[0] = '\0';
|
|
|
+ DMEMIT("%llu", (unsigned long long)atomic64_read(&ic->number_of_mismatches));
|
|
|
break;
|
|
|
|
|
|
case STATUSTYPE_TABLE: {
|
|
@@ -2634,7 +2643,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
|
|
|
memset(iv, 0x00, ivsize);
|
|
|
|
|
|
skcipher_request_set_crypt(req, sg, sg, PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, iv);
|
|
|
- comp.comp = COMPLETION_INITIALIZER_ONSTACK(comp.comp);
|
|
|
+ init_completion(&comp.comp);
|
|
|
comp.in_flight = (atomic_t)ATOMIC_INIT(1);
|
|
|
if (do_crypt(true, req, &comp))
|
|
|
wait_for_completion(&comp.comp);
|
|
@@ -2691,7 +2700,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
|
|
|
|
|
|
sg_init_one(&sg, crypt_data, crypt_len);
|
|
|
skcipher_request_set_crypt(req, &sg, &sg, crypt_len, iv);
|
|
|
- comp.comp = COMPLETION_INITIALIZER_ONSTACK(comp.comp);
|
|
|
+ init_completion(&comp.comp);
|
|
|
comp.in_flight = (atomic_t)ATOMIC_INIT(1);
|
|
|
if (do_crypt(true, req, &comp))
|
|
|
wait_for_completion(&comp.comp);
|
|
@@ -2778,7 +2787,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
|
|
int r;
|
|
|
unsigned extra_args;
|
|
|
struct dm_arg_set as;
|
|
|
- static struct dm_arg _args[] = {
|
|
|
+ static const struct dm_arg _args[] = {
|
|
|
{0, 9, "Invalid number of feature args"},
|
|
|
};
|
|
|
unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
|
|
@@ -2806,6 +2815,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
|
|
bio_list_init(&ic->flush_bio_list);
|
|
|
init_waitqueue_head(&ic->copy_to_journal_wait);
|
|
|
init_completion(&ic->crypto_backoff);
|
|
|
+ atomic64_set(&ic->number_of_mismatches, 0);
|
|
|
|
|
|
r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &ic->dev);
|
|
|
if (r) {
|
|
@@ -3202,7 +3212,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
|
|
|
|
|
|
static struct target_type integrity_target = {
|
|
|
.name = "integrity",
|
|
|
- .version = {1, 0, 0},
|
|
|
+ .version = {1, 1, 0},
|
|
|
.module = THIS_MODULE,
|
|
|
.features = DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY,
|
|
|
.ctr = dm_integrity_ctr,
|