// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2003 Sistina Software (UK) Limited. * Copyright (C) 2004, 2010-2011 Red Hat, Inc. All rights reserved. * * This file is released under the GPL.
*/
staticconststruct dm_arg _args[] = {
{0, 11, "Invalid number of feature args"},
{1, UINT_MAX, "Invalid corrupt bio byte"},
{0, 255, "Invalid corrupt value to write into bio byte (0-255)"},
{0, UINT_MAX, "Invalid corrupt bio flags mask"},
{0, PROBABILITY_BASE, "Invalid random corrupt argument"},
};
r = dm_read_arg(_args + 1, as, &fc->corrupt_bio_byte, &ti->error); if (r) return r;
argc--;
/* * Direction r or w?
*/
arg_name = dm_shift_arg(as); if (arg_name && !strcasecmp(arg_name, "w"))
fc->corrupt_bio_rw = WRITE; elseif (arg_name && !strcasecmp(arg_name, "r"))
fc->corrupt_bio_rw = READ; else {
ti->error = "Invalid corrupt bio direction (r or w)"; return -EINVAL;
}
argc--;
/* * Value of byte (0-255) to write in place of correct one.
*/
r = dm_read_arg(_args + 2, as, &fc->corrupt_bio_value, &ti->error); if (r) return r;
argc--;
/* * Only corrupt bios with these flags set.
*/
BUILD_BUG_ON(sizeof(fc->corrupt_bio_flags) != sizeof(unsignedint));
r = dm_read_arg(_args + 3, as,
(__force unsignedint *)&fc->corrupt_bio_flags,
&ti->error); if (r) return r;
argc--;
continue;
}
if (!strcasecmp(arg_name, "random_read_corrupt")) { if (fc->random_read_corrupt) {
ti->error = "Feature random_read_corrupt duplicated"; return -EINVAL;
} elseif (!argc) {
ti->error = "Feature random_read_corrupt requires a parameter"; return -EINVAL;
}
r = dm_read_arg(_args + 4, as, &fc->random_read_corrupt, &ti->error); if (r) return r;
argc--;
continue;
}
if (!strcasecmp(arg_name, "random_write_corrupt")) { if (fc->random_write_corrupt) {
ti->error = "Feature random_write_corrupt duplicated"; return -EINVAL;
} elseif (!argc) {
ti->error = "Feature random_write_corrupt requires a parameter"; return -EINVAL;
}
r = dm_read_arg(_args + 4, as, &fc->random_write_corrupt, &ti->error); if (r) return r;
argc--;
if (test_bit(DROP_WRITES, &fc->flags) &&
((fc->corrupt_bio_byte && fc->corrupt_bio_rw == WRITE) ||
fc->random_write_corrupt)) {
ti->error = "drop_writes is incompatible with random_write_corrupt or corrupt_bio_byte with the WRITE flag set"; return -EINVAL;
} elseif (test_bit(ERROR_WRITES, &fc->flags) &&
((fc->corrupt_bio_byte && fc->corrupt_bio_rw == WRITE) ||
fc->random_write_corrupt)) {
ti->error = "error_writes is incompatible with random_write_corrupt or corrupt_bio_byte with the WRITE flag set"; return -EINVAL;
} elseif (test_bit(ERROR_READS, &fc->flags) &&
((fc->corrupt_bio_byte && fc->corrupt_bio_rw == READ) ||
fc->random_read_corrupt)) {
ti->error = "error_reads is incompatible with random_read_corrupt or corrupt_bio_byte with the READ flag set"; return -EINVAL;
}
/* * Construct a flakey mapping: * <dev_path> <offset> <up interval> <down interval> [<#feature args> [<arg>]*] * * Feature args: * [drop_writes] * [corrupt_bio_byte <Nth_byte> <direction> <value> <bio_flags>] * * Nth_byte starts from 1 for the first byte. * Direction is r for READ or w for WRITE. * bio_flags is ignored if 0.
*/ staticint flakey_ctr(struct dm_target *ti, unsignedint argc, char **argv)
{ staticconststruct dm_arg _args[] = {
{0, UINT_MAX, "Invalid up interval"},
{0, UINT_MAX, "Invalid down interval"},
};
/* Are we alive ? */
elapsed = (jiffies - fc->start_time) / HZ; if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) { bool corrupt_fixed, corrupt_random;
if (bio_has_data(bio)) {
pb->bio_can_corrupt = true;
pb->saved_iter = bio->bi_iter;
}
/* * If ERROR_READS isn't set flakey_end_io() will decide if the * reads should be modified.
*/ if (bio_data_dir(bio) == READ) { if (test_bit(ERROR_READS, &fc->flags)) return DM_MAPIO_KILL; goto map_bio;
}
/* * Drop or error writes?
*/ if (test_bit(DROP_WRITES, &fc->flags)) {
bio_endio(bio); return DM_MAPIO_SUBMITTED;
} elseif (test_bit(ERROR_WRITES, &fc->flags)) {
bio_io_error(bio); return DM_MAPIO_SUBMITTED;
}
if (!pb->bio_can_corrupt) goto map_bio; /* * Corrupt matching writes.
*/
corrupt_fixed = false;
corrupt_random = false; if (fc->corrupt_bio_byte && fc->corrupt_bio_rw == WRITE) { if (all_corrupt_bio_flags_match(bio, fc))
corrupt_fixed = true;
} if (fc->random_write_corrupt) {
u64 rnd = get_random_u64();
u32 rem = do_div(rnd, PROBABILITY_BASE); if (rem < fc->random_write_corrupt)
corrupt_random = true;
} if (corrupt_fixed || corrupt_random) { struct bio *clone = clone_bio(ti, fc, bio); if (clone) { if (corrupt_fixed)
corrupt_bio_data(clone, fc,
clone->bi_iter); if (corrupt_random)
corrupt_bio_random(clone,
clone->bi_iter);
submit_bio(clone); return DM_MAPIO_SUBMITTED;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.