Skip to content

Commit

Permalink
Merge tag 'for-5.9/dm-fixes' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/device-mapper/linux-dm

Pull device mapper fixes from Mike Snitzer:

 - writecache fix to allow dax_direct_access() to partitioned pmem
   devices.

 - multipath fix to avoid any Path Group initialization if
   'pg_init_in_progress' isn't set.

 - crypt fix to use DECLARE_CRYPTO_WAIT() for onstack wait structures.

 - integrity fix to properly check integrity after device creation when
   in bitmap mode.

 - thinp and cache target __create_persistent_data_objects() fixes to
   reset the metadata's dm_block_manager pointer from PTR_ERR to NULL
   before returning from error path.

 - persistent-data block manager fix to guard against dm_block_manager
   NULL pointer dereference in dm_bm_is_read_only() and update various
   opencoded bm->read_only checks to use dm_bm_is_read_only() instead.

* tag 'for-5.9/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm thin metadata: Fix use-after-free in dm_bm_set_read_only
  dm thin metadata:  Avoid returning cmd->bm wild pointer on error
  dm cache metadata: Avoid returning cmd->bm wild pointer on error
  dm integrity: fix error reporting in bitmap mode after creation
  dm crypt: Initialize crypto wait structures
  dm mpath: fix racey management of PG initialization
  dm writecache: handle DAX to partitions on persistent memory correctly
  • Loading branch information
Linus Torvalds committed Sep 2, 2020
2 parents e1d0126 + 3a653b2 commit c3a1309
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 22 deletions.
8 changes: 6 additions & 2 deletions drivers/md/dm-cache-metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,12 +537,16 @@ static int __create_persistent_data_objects(struct dm_cache_metadata *cmd,
CACHE_MAX_CONCURRENT_LOCKS);
if (IS_ERR(cmd->bm)) {
DMERR("could not create block manager");
return PTR_ERR(cmd->bm);
r = PTR_ERR(cmd->bm);
cmd->bm = NULL;
return r;
}

r = __open_or_format_metadata(cmd, may_format_device);
if (r)
if (r) {
dm_block_manager_destroy(cmd->bm);
cmd->bm = NULL;
}

return r;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/md/dm-crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv,
u8 buf[MAX_CIPHER_BLOCKSIZE] __aligned(__alignof__(__le64));
struct skcipher_request *req;
struct scatterlist src, dst;
struct crypto_wait wait;
DECLARE_CRYPTO_WAIT(wait);
int err;

req = skcipher_request_alloc(any_tfm(cc), GFP_NOIO);
Expand Down Expand Up @@ -936,7 +936,7 @@ static int crypt_iv_elephant(struct crypt_config *cc, struct dm_crypt_request *d
u8 *es, *ks, *data, *data2, *data_offset;
struct skcipher_request *req;
struct scatterlist *sg, *sg2, src, dst;
struct crypto_wait wait;
DECLARE_CRYPTO_WAIT(wait);
int i, r;

req = skcipher_request_alloc(elephant->tfm, GFP_NOIO);
Expand Down
12 changes: 12 additions & 0 deletions drivers/md/dm-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -2487,6 +2487,7 @@ static void integrity_recalc(struct work_struct *w)
range.logical_sector = le64_to_cpu(ic->sb->recalc_sector);
if (unlikely(range.logical_sector >= ic->provided_data_sectors)) {
if (ic->mode == 'B') {
block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
DEBUG_print("queue_delayed_work: bitmap_flush_work\n");
queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, 0);
}
Expand Down Expand Up @@ -2564,6 +2565,17 @@ static void integrity_recalc(struct work_struct *w)
goto err;
}

if (ic->mode == 'B') {
sector_t start, end;
start = (range.logical_sector >>
(ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit)) <<
(ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
end = ((range.logical_sector + range.n_sectors) >>
(ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit)) <<
(ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
block_bitmap_op(ic, ic->recalc_bitmap, start, end - start, BITMAP_OP_CLEAR);
}

advance_and_next:
cond_resched();

Expand Down
22 changes: 15 additions & 7 deletions drivers/md/dm-mpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -1287,17 +1287,25 @@ static void multipath_wait_for_pg_init_completion(struct multipath *m)
static void flush_multipath_work(struct multipath *m)
{
if (m->hw_handler_name) {
set_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
smp_mb__after_atomic();
unsigned long flags;

if (!atomic_read(&m->pg_init_in_progress))
goto skip;

spin_lock_irqsave(&m->lock, flags);
if (atomic_read(&m->pg_init_in_progress) &&
!test_and_set_bit(MPATHF_PG_INIT_DISABLED, &m->flags)) {
spin_unlock_irqrestore(&m->lock, flags);

if (atomic_read(&m->pg_init_in_progress))
flush_workqueue(kmpath_handlerd);
multipath_wait_for_pg_init_completion(m);
multipath_wait_for_pg_init_completion(m);

clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
smp_mb__after_atomic();
spin_lock_irqsave(&m->lock, flags);
clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
}
spin_unlock_irqrestore(&m->lock, flags);
}

skip:
if (m->queue_mode == DM_TYPE_BIO_BASED)
flush_work(&m->process_queued_bios);
flush_work(&m->trigger_event);
Expand Down
10 changes: 7 additions & 3 deletions drivers/md/dm-thin-metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,12 +739,16 @@ static int __create_persistent_data_objects(struct dm_pool_metadata *pmd, bool f
THIN_MAX_CONCURRENT_LOCKS);
if (IS_ERR(pmd->bm)) {
DMERR("could not create block manager");
return PTR_ERR(pmd->bm);
r = PTR_ERR(pmd->bm);
pmd->bm = NULL;
return r;
}

r = __open_or_format_metadata(pmd, format_device);
if (r)
if (r) {
dm_block_manager_destroy(pmd->bm);
pmd->bm = NULL;
}

return r;
}
Expand Down Expand Up @@ -954,7 +958,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
}

pmd_write_lock_in_core(pmd);
if (!dm_bm_is_read_only(pmd->bm) && !pmd->fail_io) {
if (!pmd->fail_io && !dm_bm_is_read_only(pmd->bm)) {
r = __commit_transaction(pmd);
if (r < 0)
DMWARN("%s: __commit_transaction() failed, error = %d",
Expand Down
12 changes: 10 additions & 2 deletions drivers/md/dm-writecache.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ static int persistent_memory_claim(struct dm_writecache *wc)
pfn_t pfn;
int id;
struct page **pages;
sector_t offset;

wc->memory_vmapped = false;

Expand All @@ -245,9 +246,16 @@ static int persistent_memory_claim(struct dm_writecache *wc)
goto err1;
}

offset = get_start_sect(wc->ssd_dev->bdev);
if (offset & (PAGE_SIZE / 512 - 1)) {
r = -EINVAL;
goto err1;
}
offset >>= PAGE_SHIFT - 9;

id = dax_read_lock();

da = dax_direct_access(wc->ssd_dev->dax_dev, 0, p, &wc->memory_map, &pfn);
da = dax_direct_access(wc->ssd_dev->dax_dev, offset, p, &wc->memory_map, &pfn);
if (da < 0) {
wc->memory_map = NULL;
r = da;
Expand All @@ -269,7 +277,7 @@ static int persistent_memory_claim(struct dm_writecache *wc)
i = 0;
do {
long daa;
daa = dax_direct_access(wc->ssd_dev->dax_dev, i, p - i,
daa = dax_direct_access(wc->ssd_dev->dax_dev, offset + i, p - i,
NULL, &pfn);
if (daa <= 0) {
r = daa ? daa : -EINVAL;
Expand Down
14 changes: 8 additions & 6 deletions drivers/md/persistent-data/dm-block-manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ int dm_bm_write_lock(struct dm_block_manager *bm,
void *p;
int r;

if (bm->read_only)
if (dm_bm_is_read_only(bm))
return -EPERM;

p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result);
Expand Down Expand Up @@ -562,7 +562,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm,
struct buffer_aux *aux;
void *p;

if (bm->read_only)
if (dm_bm_is_read_only(bm))
return -EPERM;

p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result);
Expand Down Expand Up @@ -602,7 +602,7 @@ EXPORT_SYMBOL_GPL(dm_bm_unlock);

int dm_bm_flush(struct dm_block_manager *bm)
{
if (bm->read_only)
if (dm_bm_is_read_only(bm))
return -EPERM;

return dm_bufio_write_dirty_buffers(bm->bufio);
Expand All @@ -616,19 +616,21 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b)

bool dm_bm_is_read_only(struct dm_block_manager *bm)
{
return bm->read_only;
return (bm ? bm->read_only : true);
}
EXPORT_SYMBOL_GPL(dm_bm_is_read_only);

void dm_bm_set_read_only(struct dm_block_manager *bm)
{
bm->read_only = true;
if (bm)
bm->read_only = true;
}
EXPORT_SYMBOL_GPL(dm_bm_set_read_only);

void dm_bm_set_read_write(struct dm_block_manager *bm)
{
bm->read_only = false;
if (bm)
bm->read_only = false;
}
EXPORT_SYMBOL_GPL(dm_bm_set_read_write);

Expand Down

0 comments on commit c3a1309

Please sign in to comment.