aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/admin-guide/device-mapper/dm-raid.rst80
-rw-r--r--Documentation/admin-guide/device-mapper/verity.rst6
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/md/Kconfig2
-rw-r--r--drivers/md/dm-bufio.c10
-rw-r--r--drivers/md/dm-core.h1
-rw-r--r--drivers/md/dm-crypt.c117
-rw-r--r--drivers/md/dm-ebs-target.c2
-rw-r--r--drivers/md/dm-exception-store.h2
-rw-r--r--drivers/md/dm-log-writes.c1
-rw-r--r--drivers/md/dm-mpath.c63
-rw-r--r--drivers/md/dm-pcache/cache.c13
-rw-r--r--drivers/md/dm-pcache/cache_segment.c13
-rw-r--r--drivers/md/dm-raid.c2
-rw-r--r--drivers/md/dm-snap.c73
-rw-r--r--drivers/md/dm-sysfs.c8
-rw-r--r--drivers/md/dm-table.c4
-rw-r--r--drivers/md/dm-thin.c19
-rw-r--r--drivers/md/dm-vdo/action-manager.c2
-rw-r--r--drivers/md/dm-vdo/admin-state.c75
-rw-r--r--drivers/md/dm-vdo/block-map.c51
-rw-r--r--drivers/md/dm-vdo/completion.c5
-rw-r--r--drivers/md/dm-vdo/data-vio.c34
-rw-r--r--drivers/md/dm-vdo/dedupe.c42
-rw-r--r--drivers/md/dm-vdo/dm-vdo-target.c5
-rw-r--r--drivers/md/dm-vdo/encodings.c26
-rw-r--r--drivers/md/dm-vdo/flush.c6
-rw-r--r--drivers/md/dm-vdo/funnel-workqueue.c7
-rw-r--r--drivers/md/dm-vdo/io-submitter.c26
-rw-r--r--drivers/md/dm-vdo/logical-zone.c20
-rw-r--r--drivers/md/dm-vdo/packer.c15
-rw-r--r--drivers/md/dm-vdo/physical-zone.c5
-rw-r--r--drivers/md/dm-vdo/recovery-journal.c30
-rw-r--r--drivers/md/dm-vdo/slab-depot.c96
-rw-r--r--drivers/md/dm-vdo/vdo.c9
-rw-r--r--drivers/md/dm-vdo/vdo.h4
-rw-r--r--drivers/md/dm-vdo/vio.c3
-rw-r--r--drivers/md/dm-vdo/vio.h6
-rw-r--r--drivers/md/dm-verity-fec.c41
-rw-r--r--drivers/md/dm-verity-fec.h10
-rw-r--r--drivers/md/dm-verity-target.c209
-rw-r--r--drivers/md/dm-verity.h52
-rw-r--r--drivers/md/dm-zone.c3
-rw-r--r--drivers/md/dm.c46
44 files changed, 761 insertions, 484 deletions
diff --git a/Documentation/admin-guide/device-mapper/dm-raid.rst b/Documentation/admin-guide/device-mapper/dm-raid.rst
index bb17e26e3c1b..e11f10764770 100644
--- a/Documentation/admin-guide/device-mapper/dm-raid.rst
+++ b/Documentation/admin-guide/device-mapper/dm-raid.rst
@@ -20,10 +20,10 @@ The target is named "raid" and it accepts the following parameters::
raid0 RAID0 striping (no resilience)
raid1 RAID1 mirroring
raid4 RAID4 with dedicated last parity disk
- raid5_n RAID5 with dedicated last parity disk supporting takeover
+ raid5_n RAID5 with dedicated last parity disk supporting takeover from/to raid1
Same as raid4
- - Transitory layout
+ - Transitory layout for takeover from/to raid1
raid5_la RAID5 left asymmetric
- rotating parity 0 with data continuation
@@ -48,8 +48,8 @@ The target is named "raid" and it accepts the following parameters::
raid6_n_6 RAID6 with dedicate parity disks
- parity and Q-syndrome on the last 2 disks;
- layout for takeover from/to raid4/raid5_n
- raid6_la_6 Same as "raid_la" plus dedicated last Q-syndrome disk
+ layout for takeover from/to raid0/raid4/raid5_n
+ raid6_la_6 Same as "raid_la" plus dedicated last Q-syndrome disk supporting takeover from/to raid5
- layout for takeover from raid5_la from/to raid6
raid6_ra_6 Same as "raid5_ra" dedicated last Q-syndrome disk
@@ -173,9 +173,9 @@ The target is named "raid" and it accepts the following parameters::
The delta_disks option value (-251 < N < +251) triggers
device removal (negative value) or device addition (positive
value) to any reshape supporting raid levels 4/5/6 and 10.
- RAID levels 4/5/6 allow for addition of devices (metadata
- and data device tuple), raid10_near and raid10_offset only
- allow for device addition. raid10_far does not support any
+ RAID levels 4/5/6 allow for addition and removal of devices
+ (metadata and data device tuple), raid10_near and raid10_offset
+ only allow for device addition. raid10_far does not support any
reshaping at all.
A minimum of devices have to be kept to enforce resilience,
which is 3 devices for raid4/5 and 4 devices for raid6.
@@ -372,6 +372,72 @@ to safely enable discard support for RAID 4/5/6:
'devices_handle_discards_safely'
+Takeover/Reshape Support
+------------------------
+The target natively supports these two types of MDRAID conversions:
+
+o Takeover: Converts an array from one RAID level to another
+
+o Reshape: Changes the internal layout while maintaining the current RAID level
+
+Each operation is only valid under specific constraints imposed by the existing array's layout and configuration.
+
+
+Takeover:
+linear -> raid1 with N >= 2 mirrors
+raid0 -> raid4 (add dedicated parity device)
+raid0 -> raid5 (add dedicated parity device)
+raid0 -> raid10 with near layout and N >= 2 mirror groups (raid0 stripes have to become first member within mirror groups)
+raid1 -> linear
+raid1 -> raid5 with 2 mirrors
+raid4 -> raid5 w/ rotating parity
+raid5 with dedicated parity device -> raid4
+raid5 -> raid6 (with dedicated Q-syndrome)
+raid6 (with dedicated Q-syndrome) -> raid5
+raid10 with near layout and even number of disks -> raid0 (select any in-sync device from each mirror group)
+
+Reshape:
+linear: not possible
+raid0: not possible
+raid1: change number of mirrors
+raid4: add and remove stripes (minimum 3), change stripesize
+raid5: add and remove stripes (minimum 3, special case 2 for raid1 takeover), change rotating parity algorithms, change stripesize
+raid6: add and remove stripes (minimum 4), change rotating syndrome algorithms, change stripesize
+raid10 near: add stripes (minimum 4), change stripesize, no stripe removal possible, change to offset layout
+raid10 offset: add stripes, change stripesize, no stripe removal possible, change to near layout
+raid10 far: not possible
+
+Table line examples:
+
+### raid1 -> raid5
+#
+# 2 devices limitation in raid1.
+# raid5 personality is able to just map 2 like raid1.
+# Reshape after takeover to change to full raid5 layout
+
+ 0 1960886272 raid raid1 3 0 region_size 2048 2 /dev/dm-0 /dev/dm-1 /dev/dm-2 /dev/dm-3
+
+# dm-0 and dm-2 are e.g. 4MiB large metadata devices, dm-1 and dm-3 have to be at least 1960886272 big.
+#
+# Table line to takeover to raid5
+
+ 0 1960886272 raid raid5 3 0 region_size 2048 2 /dev/dm-0 /dev/dm-1 /dev/dm-2 /dev/dm-3
+
+# Add required out-of-place reshape space to the beginniong of the given 2 data devices,
+# allocate another metadata/data device tuple with the same sizes for the parity space
+# and zero the first 4K of the metadata device.
+#
+# Example table of the out-of-place reshape space addition for one data device, e.g. dm-1
+
+ 0 8192 linear 8:0 0 1960903888 # <- must be free space segment
+ 8192 1960886272 linear 8:0 0 2048 # previous data segment
+
+# Mapping table for e.g. raid5_rs reshape causing the size of the raid device to double-fold once the reshape finishes.
+# Check the status output (e.g. "dmsetup status $RaidDev") for progess.
+
+ 0 $((2 * 1960886272)) raid raid5 7 0 region_size 2048 data_offset 8192 delta_disk 1 2 /dev/dm-0 /dev/dm-1 /dev/dm-2 /dev/dm-3
+
+
Version History
---------------
diff --git a/Documentation/admin-guide/device-mapper/verity.rst b/Documentation/admin-guide/device-mapper/verity.rst
index 8c3f1f967a3c..3ecab1cff9c6 100644
--- a/Documentation/admin-guide/device-mapper/verity.rst
+++ b/Documentation/admin-guide/device-mapper/verity.rst
@@ -236,8 +236,10 @@ is available at the cryptsetup project's wiki page
Status
======
-V (for Valid) is returned if every check performed so far was valid.
-If any check failed, C (for Corruption) is returned.
+1. V (for Valid) is returned if every check performed so far was valid.
+ If any check failed, C (for Corruption) is returned.
+2. Number of corrected blocks by Forward Error Correction.
+ '-' if Forward Error Correction is not enabled.
Example
=======
diff --git a/MAINTAINERS b/MAINTAINERS
index aff3e162180d..c9e416ba74c6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7225,6 +7225,7 @@ DEVICE-MAPPER (LVM)
M: Alasdair Kergon <agk@redhat.com>
M: Mike Snitzer <snitzer@kernel.org>
M: Mikulas Patocka <mpatocka@redhat.com>
+M: Benjamin Marzinski <bmarzins@redhat.com>
L: dm-devel@lists.linux.dev
S: Maintained
Q: http://patchwork.kernel.org/project/dm-devel/list/
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 104aa5355090..239c1744a926 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -299,6 +299,7 @@ config DM_CRYPT
select CRYPTO
select CRYPTO_CBC
select CRYPTO_ESSIV
+ select CRYPTO_LIB_MD5 # needed by lmk IV mode
help
This device-mapper target allows you to create a device that
transparently encrypts the data on it. You'll need to activate
@@ -546,6 +547,7 @@ config DM_VERITY
depends on BLK_DEV_DM
select CRYPTO
select CRYPTO_HASH
+ select CRYPTO_LIB_SHA256
select DM_BUFIO
help
This device-mapper target creates a read-only device that
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index e6d28be11c5c..5235f3e4924b 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1374,7 +1374,7 @@ static void submit_io(struct dm_buffer *b, enum req_op op, unsigned short ioprio
{
unsigned int n_sectors;
sector_t sector;
- unsigned int offset, end;
+ unsigned int offset, end, align;
b->end_io = end_io;
@@ -1388,9 +1388,11 @@ static void submit_io(struct dm_buffer *b, enum req_op op, unsigned short ioprio
b->c->write_callback(b);
offset = b->write_start;
end = b->write_end;
- offset &= -DM_BUFIO_WRITE_ALIGN;
- end += DM_BUFIO_WRITE_ALIGN - 1;
- end &= -DM_BUFIO_WRITE_ALIGN;
+ align = max(DM_BUFIO_WRITE_ALIGN,
+ bdev_physical_block_size(b->c->bdev));
+ offset &= -align;
+ end += align - 1;
+ end &= -align;
if (unlikely(end > b->c->block_size))
end = b->c->block_size;
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index a3c9f74fe2dc..1cda8618d74d 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -139,7 +139,6 @@ struct mapped_device {
struct srcu_struct io_barrier;
#ifdef CONFIG_BLK_DEV_ZONED
- unsigned int nr_zones;
void *zone_revalidate_map;
struct task_struct *revalidate_map_task;
#endif
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 5ef43231fe77..79704fbc523b 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -21,6 +21,7 @@
#include <linux/mempool.h>
#include <linux/slab.h>
#include <linux/crypto.h>
+#include <linux/fips.h>
#include <linux/workqueue.h>
#include <linux/kthread.h>
#include <linux/backing-dev.h>
@@ -120,7 +121,6 @@ struct iv_benbi_private {
#define LMK_SEED_SIZE 64 /* hash + 0 */
struct iv_lmk_private {
- struct crypto_shash *hash_tfm;
u8 *seed;
};
@@ -254,22 +254,15 @@ static unsigned int max_write_size = 0;
module_param(max_write_size, uint, 0644);
MODULE_PARM_DESC(max_write_size, "Maximum size of a write request");
-static unsigned get_max_request_sectors(struct dm_target *ti, struct bio *bio)
+static unsigned get_max_request_sectors(struct dm_target *ti, struct bio *bio, bool no_split)
{
struct crypt_config *cc = ti->private;
unsigned val, sector_align;
bool wrt = op_is_write(bio_op(bio));
- if (wrt) {
- /*
- * For zoned devices, splitting write operations creates the
- * risk of deadlocking queue freeze operations with zone write
- * plugging BIO work when the reminder of a split BIO is
- * issued. So always allow the entire BIO to proceed.
- */
- if (ti->emulate_zone_append)
- return bio_sectors(bio);
-
+ if (no_split) {
+ val = -1;
+ } else if (wrt) {
val = min_not_zero(READ_ONCE(max_write_size),
DM_CRYPT_DEFAULT_MAX_WRITE_SIZE);
} else {
@@ -465,10 +458,6 @@ static void crypt_iv_lmk_dtr(struct crypt_config *cc)
{
struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk;
- if (lmk->hash_tfm && !IS_ERR(lmk->hash_tfm))
- crypto_free_shash(lmk->hash_tfm);
- lmk->hash_tfm = NULL;
-
kfree_sensitive(lmk->seed);
lmk->seed = NULL;
}
@@ -483,11 +472,10 @@ static int crypt_iv_lmk_ctr(struct crypt_config *cc, struct dm_target *ti,
return -EINVAL;
}
- lmk->hash_tfm = crypto_alloc_shash("md5", 0,
- CRYPTO_ALG_ALLOCATES_MEMORY);
- if (IS_ERR(lmk->hash_tfm)) {
- ti->error = "Error initializing LMK hash";
- return PTR_ERR(lmk->hash_tfm);
+ if (fips_enabled) {
+ ti->error = "LMK support is disabled due to FIPS";
+ /* ... because it uses MD5. */
+ return -EINVAL;
}
/* No seed in LMK version 2 */
@@ -498,7 +486,6 @@ static int crypt_iv_lmk_ctr(struct crypt_config *cc, struct dm_target *ti,
lmk->seed = kzalloc(LMK_SEED_SIZE, GFP_KERNEL);
if (!lmk->seed) {
- crypt_iv_lmk_dtr(cc);
ti->error = "Error kmallocing seed storage in LMK";
return -ENOMEM;
}
@@ -514,7 +501,7 @@ static int crypt_iv_lmk_init(struct crypt_config *cc)
/* LMK seed is on the position of LMK_KEYS + 1 key */
if (lmk->seed)
memcpy(lmk->seed, cc->key + (cc->tfms_count * subkey_size),
- crypto_shash_digestsize(lmk->hash_tfm));
+ MD5_DIGEST_SIZE);
return 0;
}
@@ -529,55 +516,31 @@ static int crypt_iv_lmk_wipe(struct crypt_config *cc)
return 0;
}
-static int crypt_iv_lmk_one(struct crypt_config *cc, u8 *iv,
- struct dm_crypt_request *dmreq,
- u8 *data)
+static void crypt_iv_lmk_one(struct crypt_config *cc, u8 *iv,
+ struct dm_crypt_request *dmreq, u8 *data)
{
struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk;
- SHASH_DESC_ON_STACK(desc, lmk->hash_tfm);
- union {
- struct md5_state md5state;
- u8 state[CRYPTO_MD5_STATESIZE];
- } u;
+ struct md5_ctx ctx;
__le32 buf[4];
- int i, r;
- desc->tfm = lmk->hash_tfm;
+ md5_init(&ctx);
- r = crypto_shash_init(desc);
- if (r)
- return r;
-
- if (lmk->seed) {
- r = crypto_shash_update(desc, lmk->seed, LMK_SEED_SIZE);
- if (r)
- return r;
- }
+ if (lmk->seed)
+ md5_update(&ctx, lmk->seed, LMK_SEED_SIZE);
/* Sector is always 512B, block size 16, add data of blocks 1-31 */
- r = crypto_shash_update(desc, data + 16, 16 * 31);
- if (r)
- return r;
+ md5_update(&ctx, data + 16, 16 * 31);
/* Sector is cropped to 56 bits here */
buf[0] = cpu_to_le32(dmreq->iv_sector & 0xFFFFFFFF);
buf[1] = cpu_to_le32((((u64)dmreq->iv_sector >> 32) & 0x00FFFFFF) | 0x80000000);
buf[2] = cpu_to_le32(4024);
buf[3] = 0;
- r = crypto_shash_update(desc, (u8 *)buf, sizeof(buf));
- if (r)
- return r;
+ md5_update(&ctx, (u8 *)buf, sizeof(buf));
/* No MD5 padding here */
- r = crypto_shash_export(desc, &u.md5state);
- if (r)
- return r;
-
- for (i = 0; i < MD5_HASH_WORDS; i++)
- __cpu_to_le32s(&u.md5state.hash[i]);
- memcpy(iv, &u.md5state.hash, cc->iv_size);
-
- return 0;
+ cpu_to_le32_array(ctx.state.h, ARRAY_SIZE(ctx.state.h));
+ memcpy(iv, ctx.state.h, cc->iv_size);
}
static int crypt_iv_lmk_gen(struct crypt_config *cc, u8 *iv,
@@ -585,17 +548,15 @@ static int crypt_iv_lmk_gen(struct crypt_config *cc, u8 *iv,
{
struct scatterlist *sg;
u8 *src;
- int r = 0;
if (bio_data_dir(dmreq->ctx->bio_in) == WRITE) {
sg = crypt_get_sg_data(cc, dmreq->sg_in);
src = kmap_local_page(sg_page(sg));
- r = crypt_iv_lmk_one(cc, iv, dmreq, src + sg->offset);
+ crypt_iv_lmk_one(cc, iv, dmreq, src + sg->offset);
kunmap_local(src);
} else
memset(iv, 0, cc->iv_size);
-
- return r;
+ return 0;
}
static int crypt_iv_lmk_post(struct crypt_config *cc, u8 *iv,
@@ -603,21 +564,19 @@ static int crypt_iv_lmk_post(struct crypt_config *cc, u8 *iv,
{
struct scatterlist *sg;
u8 *dst;
- int r;
if (bio_data_dir(dmreq->ctx->bio_in) == WRITE)
return 0;
sg = crypt_get_sg_data(cc, dmreq->sg_out);
dst = kmap_local_page(sg_page(sg));
- r = crypt_iv_lmk_one(cc, iv, dmreq, dst + sg->offset);
+ crypt_iv_lmk_one(cc, iv, dmreq, dst + sg->offset);
/* Tweak the first block of plaintext sector */
- if (!r)
- crypto_xor(dst + sg->offset, iv, cc->iv_size);
+ crypto_xor(dst + sg->offset, iv, cc->iv_size);
kunmap_local(dst);
- return r;
+ return 0;
}
static void crypt_iv_tcw_dtr(struct crypt_config *cc)
@@ -1781,7 +1740,7 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
bio_for_each_folio_all(fi, clone) {
if (folio_test_large(fi.folio)) {
percpu_counter_sub(&cc->n_allocated_pages,
- 1 << folio_order(fi.folio));
+ folio_nr_pages(fi.folio));
folio_put(fi.folio);
} else {
mempool_free(&fi.folio->page, &cc->page_pool);
@@ -3496,6 +3455,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
struct dm_crypt_io *io;
struct crypt_config *cc = ti->private;
unsigned max_sectors;
+ bool no_split;
/*
* If bio is REQ_PREFLUSH or REQ_OP_DISCARD, just bypass crypt queues.
@@ -3513,10 +3473,20 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
/*
* Check if bio is too large, split as needed.
+ *
+ * For zoned devices, splitting write operations creates the
+ * risk of deadlocking queue freeze operations with zone write
+ * plugging BIO work when the reminder of a split BIO is
+ * issued. So always allow the entire BIO to proceed.
*/
- max_sectors = get_max_request_sectors(ti, bio);
- if (unlikely(bio_sectors(bio) > max_sectors))
+ no_split = (ti->emulate_zone_append && op_is_write(bio_op(bio))) ||
+ (bio->bi_opf & REQ_ATOMIC);
+ max_sectors = get_max_request_sectors(ti, bio, no_split);
+ if (unlikely(bio_sectors(bio) > max_sectors)) {
+ if (unlikely(no_split))
+ return DM_MAPIO_KILL;
dm_accept_partial_bio(bio, max_sectors);
+ }
/*
* Ensure that bio is a multiple of internal sector encryption size
@@ -3762,15 +3732,20 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
if (ti->emulate_zone_append)
limits->max_hw_sectors = min(limits->max_hw_sectors,
BIO_MAX_VECS << PAGE_SECTORS_SHIFT);
+
+ limits->atomic_write_hw_unit_max = min(limits->atomic_write_hw_unit_max,
+ BIO_MAX_VECS << PAGE_SHIFT);
+ limits->atomic_write_hw_max = min(limits->atomic_write_hw_max,
+ BIO_MAX_VECS << PAGE_SHIFT);
}
static struct target_type crypt_target = {
.name = "crypt",
- .version = {1, 28, 0},
+ .version = {1, 29, 0},
.module = THIS_MODULE,
.ctr = crypt_ctr,
.dtr = crypt_dtr,
- .features = DM_TARGET_ZONED_HM,
+ .features = DM_TARGET_ZONED_HM | DM_TARGET_ATOMIC_WRITES,
.report_zones = crypt_report_zones,
.map = crypt_map,
.status = crypt_status,
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c
index 6abb31ca9662..b354e74a670e 100644
--- a/drivers/md/dm-ebs-target.c
+++ b/drivers/md/dm-ebs-target.c
@@ -103,7 +103,7 @@ static int __ebs_rw_bvec(struct ebs_c *ec, enum req_op op, struct bio_vec *bv,
} else {
flush_dcache_page(bv->bv_page);
memcpy(ba, pa, cur_len);
- dm_bufio_mark_partial_buffer_dirty(b, buf_off, buf_off + cur_len);
+ dm_bufio_mark_buffer_dirty(b);
}
dm_bufio_release(b);
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index b67976637538..061b4d310813 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -29,7 +29,7 @@ typedef sector_t chunk_t;
* chunk within the device.
*/
struct dm_exception {
- struct hlist_bl_node hash_list;
+ struct hlist_node hash_list;
chunk_t old_chunk;
chunk_t new_chunk;
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index 7bb7174f8f4f..f0c84e7a5daa 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -432,6 +432,7 @@ static int log_writes_kthread(void *arg)
struct log_writes_c *lc = arg;
sector_t sector = 0;
+ set_freezable();
while (!kthread_should_stop()) {
bool super = false;
bool logging_enabled;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index aaf4a0a4b0eb..c18358271618 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -131,7 +131,7 @@ static void queue_if_no_path_timeout_work(struct timer_list *t);
#define MPATHF_QUEUE_IO 0 /* Must we queue all I/O? */
#define MPATHF_QUEUE_IF_NO_PATH 1 /* Queue I/O if last path fails? */
#define MPATHF_SAVED_QUEUE_IF_NO_PATH 2 /* Saved state during suspension */
-#define MPATHF_RETAIN_ATTACHED_HW_HANDLER 3 /* If there's already a hw_handler present, don't change it. */
+/* MPATHF_RETAIN_ATTACHED_HW_HANDLER no longer has any effect */
#define MPATHF_PG_INIT_DISABLED 4 /* pg_init is not currently allowed */
#define MPATHF_PG_INIT_REQUIRED 5 /* pg_init needs calling? */
#define MPATHF_PG_INIT_DELAY_RETRY 6 /* Delay pg_init retry? */
@@ -237,16 +237,10 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
static int alloc_multipath_stage2(struct dm_target *ti, struct multipath *m)
{
- if (m->queue_mode == DM_TYPE_NONE) {
+ if (m->queue_mode == DM_TYPE_NONE)
m->queue_mode = DM_TYPE_REQUEST_BASED;
- } else if (m->queue_mode == DM_TYPE_BIO_BASED) {
+ else if (m->queue_mode == DM_TYPE_BIO_BASED)
INIT_WORK(&m->process_queued_bios, process_queued_bios);
- /*
- * bio-based doesn't support any direct scsi_dh management;
- * it just discovers if a scsi_dh is attached.
- */
- set_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags);
- }
dm_table_set_type(ti->table, m->queue_mode);
@@ -887,36 +881,30 @@ static int setup_scsi_dh(struct block_device *bdev, struct multipath *m,
struct request_queue *q = bdev_get_queue(bdev);
int r;
- if (mpath_double_check_test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, m)) {
-retain:
- if (*attached_handler_name) {
- /*
- * Clear any hw_handler_params associated with a
- * handler that isn't already attached.
- */
- if (m->hw_handler_name && strcmp(*attached_handler_name, m->hw_handler_name)) {
- kfree(m->hw_handler_params);
- m->hw_handler_params = NULL;
- }
-
- /*
- * Reset hw_handler_name to match the attached handler
- *
- * NB. This modifies the table line to show the actual
- * handler instead of the original table passed in.
- */
- kfree(m->hw_handler_name);
- m->hw_handler_name = *attached_handler_name;
- *attached_handler_name = NULL;
+ if (*attached_handler_name) {
+ /*
+ * Clear any hw_handler_params associated with a
+ * handler that isn't already attached.
+ */
+ if (m->hw_handler_name && strcmp(*attached_handler_name,
+ m->hw_handler_name)) {
+ kfree(m->hw_handler_params);
+ m->hw_handler_params = NULL;
}
+
+ /*
+ * Reset hw_handler_name to match the attached handler
+ *
+ * NB. This modifies the table line to show the actual
+ * handler instead of the original table passed in.
+ */
+ kfree(m->hw_handler_name);
+ m->hw_handler_name = *attached_handler_name;
+ *attached_handler_name = NULL;
}
if (m->hw_handler_name) {
r = scsi_dh_attach(q, m->hw_handler_name);
- if (r == -EBUSY) {
- DMINFO("retaining handler on device %pg", bdev);
- goto retain;
- }
if (r < 0) {
*error = "error attaching hardware handler";
return r;
@@ -1138,7 +1126,7 @@ static int parse_features(struct dm_arg_set *as, struct multipath *m)
}
if (!strcasecmp(arg_name, "retain_attached_hw_handler")) {
- set_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags);
+ /* no longer has any effect */
continue;
}
@@ -1823,7 +1811,6 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
DMEMIT("%u ", test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) +
(m->pg_init_retries > 0) * 2 +
(m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) * 2 +
- test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags) +
(m->queue_mode != DM_TYPE_REQUEST_BASED) * 2);
if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
@@ -1832,8 +1819,6 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
DMEMIT("pg_init_retries %u ", m->pg_init_retries);
if (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT)
DMEMIT("pg_init_delay_msecs %u ", m->pg_init_delay_msecs);
- if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags))
- DMEMIT("retain_attached_hw_handler ");
if (m->queue_mode != DM_TYPE_REQUEST_BASED) {
switch (m->queue_mode) {
case DM_TYPE_BIO_BASED:
@@ -2307,7 +2292,7 @@ static struct target_type multipath_target = {
.name = "multipath",
.version = {1, 15, 0},
.features = DM_TARGET_SINGLETON | DM_TARGET_IMMUTABLE |
- DM_TARGET_PASSES_INTEGRITY,
+ DM_TARGET_PASSES_INTEGRITY | DM_TARGET_ATOMIC_WRITES,
.module = THIS_MODULE,
.ctr = multipath_ctr,
.dtr = multipath_dtr,
diff --git a/drivers/md/dm-pcache/cache.c b/drivers/md/dm-pcache/cache.c
index 698697a7a73c..534bf07b794f 100644
--- a/drivers/md/dm-pcache/cache.c
+++ b/drivers/md/dm-pcache/cache.c
@@ -10,7 +10,8 @@ struct kmem_cache *key_cache;
static inline struct pcache_cache_info *get_cache_info_addr(struct pcache_cache *cache)
{
- return cache->cache_info_addr + cache->info_index;
+ return (struct pcache_cache_info *)((char *)cache->cache_info_addr +
+ (size_t)cache->info_index * PCACHE_CACHE_INFO_SIZE);
}
static void cache_info_write(struct pcache_cache *cache)
@@ -21,10 +22,10 @@ static void cache_info_write(struct pcache_cache *cache)
cache_info->header.crc = pcache_meta_crc(&cache_info->header,
sizeof(struct pcache_cache_info));
+ cache->info_index = (cache->info_index + 1) % PCACHE_META_INDEX_MAX;
memcpy_flushcache(get_cache_info_addr(cache), cache_info,
sizeof(struct pcache_cache_info));
-
- cache->info_index = (cache->info_index + 1) % PCACHE_META_INDEX_MAX;
+ pmem_wmb();
}
static void cache_info_init_default(struct pcache_cache *cache);
@@ -49,6 +50,8 @@ static int cache_info_init(struct pcache_cache *cache, struct pcache_cache_optio
return -EINVAL;
}
+ cache->info_index = ((char *)cache_info_addr - (char *)cache->cache_info_addr) / PCACHE_CACHE_INFO_SIZE;
+
return 0;
}
@@ -93,10 +96,10 @@ void cache_pos_encode(struct pcache_cache *cache,
pos_onmedia.header.seq = seq;
pos_onmedia.header.crc = cache_pos_onmedia_crc(&pos_onmedia);
+ *index = (*index + 1) % PCACHE_META_INDEX_MAX;
+
memcpy_flushcache(pos_onmedia_addr, &pos_onmedia, sizeof(struct pcache_cache_pos_onmedia));
pmem_wmb();
-
- *index = (*index + 1) % PCACHE_META_INDEX_MAX;
}
int cach